diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..7f18b59
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,24 @@
+{
+ "printWidth": 160,
+ "tabWidth": 2,
+ "useTabs": false,
+ "semi": true,
+ "singleQuote": true,
+ "trailingComma": "es5",
+ "bracketSpacing": true,
+ "arrowParens": "avoid",
+ "overrides": [
+ {
+ "files": "*.html",
+ "options": {
+ "parser": "html"
+ }
+ },
+ {
+ "files": "*.js",
+ "options": {
+ "parser": "babel"
+ }
+ }
+ ]
+}
diff --git a/backend/config/db.js b/backend/config/db.js
index 9cbdc2f..6b26fd8 100644
--- a/backend/config/db.js
+++ b/backend/config/db.js
@@ -2,17 +2,16 @@ const mongoose = require('mongoose');
require('dotenv').config();
const connectDB = async () => {
- try {
- await mongoose.connect(process.env.MONGO_URI, {
- useNewUrlParser: true,
- useUnifiedTopology: true,
- });
- console.log('MongoDB connected...');
- }
- catch (err) {
- console.error(err.message);
- process.exit(1);
- }
+ try {
+ await mongoose.connect(process.env.MONGO_URI, {
+ useNewUrlParser: true,
+ useUnifiedTopology: true,
+ });
+ console.log('MongoDB connected...');
+ } catch (err) {
+ console.error(err.message);
+ process.exit(1);
+ }
};
module.exports = connectDB;
diff --git a/backend/index.js b/backend/index.js
index 89a9090..9b5ef19 100644
--- a/backend/index.js
+++ b/backend/index.js
@@ -15,9 +15,9 @@ const PORT = process.env.PORT || 5000;
// Database Connection
mongoose
- .connect(process.env.MONGO_URI, { })
- .then(() => console.log('MongoDB Connected'))
- .catch((err) => console.log(err));
+ .connect(process.env.MONGO_URI, {})
+ .then(() => console.log('MongoDB Connected'))
+ .catch(err => console.log(err));
// Middleware
app.use(cors());
@@ -32,8 +32,8 @@ app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
// Seed database on startup
seedDB().then(() => {
- // Start Server after seeding
- app.listen(PORT, () => {
- console.log(`Server listening on port ${PORT}`);
- });
+ // Start Server after seeding
+ app.listen(PORT, () => {
+ console.log(`Server listening on port ${PORT}`);
+ });
});
diff --git a/backend/routes/checkout.js b/backend/routes/checkout.js
index 83e294e..0f89178 100644
--- a/backend/routes/checkout.js
+++ b/backend/routes/checkout.js
@@ -109,8 +109,7 @@ router.post('/create-order', async (req, res) => {
await new Promise(resolve => setTimeout(resolve, 3000));
res.status(201).json({ message: 'Order created successfully!' });
- }
- catch (error) {
+ } catch (error) {
console.error('Error creating order:', error);
res.status(500).json({ error: 'Failed to create order' });
}
diff --git a/backend/routes/products.js b/backend/routes/products.js
index 684240d..1b40175 100644
--- a/backend/routes/products.js
+++ b/backend/routes/products.js
@@ -54,8 +54,7 @@ router.get('/', async (req, res) => {
}));
res.json(formattedProducts);
- }
- catch (err) {
+ } catch (err) {
res.status(500).send('Server error');
}
});
@@ -90,8 +89,7 @@ router.get('/:id', async (req, res) => {
return res.status(404).send('Product not found');
}
res.json(product);
- }
- catch (err) {
+ } catch (err) {
res.status(500).send('Server error');
}
});
@@ -123,8 +121,7 @@ router.get('/category/:category', async (req, res) => {
try {
const products = await Product.find({ category: req.params.category });
res.json(products);
- }
- catch (err) {
+ } catch (err) {
res.status(500).send('Server error');
}
});
diff --git a/backend/routes/search.js b/backend/routes/search.js
index 0692185..c012ea8 100644
--- a/backend/routes/search.js
+++ b/backend/routes/search.js
@@ -67,15 +67,12 @@ router.get('/', async (req, res) => {
const query = req.query.q;
const products = await Product.find({
- $or: [
- { name: { $regex: query, $options: 'i' } },
- { description: { $regex: query, $options: 'i' } }
- ]
+ $or: [{ name: { $regex: query, $options: 'i' } }, { description: { $regex: query, $options: 'i' } }],
});
res.json(products);
} catch (error) {
- console.error("Error searching products:", error);
+ console.error('Error searching products:', error);
res.status(500).json({ error: 'An error occurred during the search.' });
}
});
diff --git a/backend/seed/productSeeds.js b/backend/seed/productSeeds.js
index 93207b9..84c42ba 100644
--- a/backend/seed/productSeeds.js
+++ b/backend/seed/productSeeds.js
@@ -5,221 +5,222 @@ const mongoose = require('mongoose');
// Sample product data -- to be replaced with actual products
const productSeeds = [
- {
- name: 'iPhone 15 Pro Max',
- description: 'Apple\'s latest flagship smartphone.',
- price: 1099,
- category: 'electronics',
- image: 'https://cdn.tgdd.vn/Products/Images/42/305658/iphone-15-pro-max-blue-thumbnew-600x600.jpg',
- brand: 'Apple',
- stock: 100,
- },
- {
- name: 'MacBook Air M2',
- description: 'Powerful and lightweight laptop from Apple.',
- price: 1199,
- category: 'computers',
- image: 'https://cdn8.web4s.vn/media/products/mac-air-m2/macbookairm2-midnight%201.jpg',
- brand: 'Apple',
- stock: 50,
- },
- {
- name: 'Sony WH-1000XM5 Headphones',
- description: 'Industry-leading noise-canceling headphones.',
- price: 399,
- category: 'electronics',
- image: 'https://bizweb.dktcdn.net/100/340/129/products/wh1000xm5-midnightblue-2-cuongphanvn.jpg?v=1714306049613',
- brand: 'Sony',
- stock: 200,
- },
- {
- name: 'Samsung 65" QLED TV',
- description: 'Immersive 4K TV experience with QLED technology.',
- price: 1499,
- category: 'electronics',
- image: 'https://cdn.mediamart.vn/images/product/qled-tivi-4k-samsung-65-inch-65q80c-smart-tv_5304e716.png', // Replace with actual image URL
- brand: 'Samsung',
- stock: 10,
- },
- {
- name: 'Canon EOS R5',
- description: 'High-performance mirrorless camera from Canon.',
- price: 3799,
- category: 'electronics',
- image: 'https://i1.adis.ws/i/canon/eos-r5_front_rf24-105mmf4lisusm_square_32c26ad194234d42b3cd9e582a21c99b',
- brand: 'Canon',
- stock: 5,
- },
- {
- name: 'Apple Watch Series 7',
- description: 'Stay connected and healthy with the latest Apple Watch.',
- price: 399,
- category: 'electronics',
- image: 'https://akbroshop.com/wp-content/uploads/2022/08/hinh-aw-s7-xanh.jpg',
- brand: 'Apple',
- stock: 100,
- },
- {
- name: 'Dell XPS 15',
- description: 'Powerful laptop with stunning 4K display.',
- price: 1799,
- category: 'computers',
- image: 'https://minhvu.vn/thumb/dellxps/dellxps159530/dellxps159530cbfbjco_480_360.jpg',
- brand: 'Dell',
- stock: 20,
- },
- {
- name: 'Samsung Galaxy Tab S7+',
- description: 'Premium Android tablet with stunning AMOLED display.',
- price: 849,
- category: 'electronics',
- image: 'https://hanoicomputercdn.com/media/product/60370_may_tinh_bang_samsung_galaxy_tab_s7_plus_128gb_den.png',
- brand: 'Samsung',
- stock: 30,
- },
- {
- name: 'Sony A7 IV',
- description: 'Full-frame mirrorless camera with 33MP sensor.',
- price: 2499,
- category: 'electronics',
- image: 'https://zshop.vn/images/detailed/92/1634812545_1667800.jpg',
- brand: 'Sony',
- stock: 10,
- },
- {
- name: 'LG C1 OLED TV',
- description: 'Stunning OLED TV with great picture quality.',
- price: 1999,
- category: 'electronics',
- image: 'https://product.hstatic.net/200000574527/product/dz-6_ac9672a6534245fcbb1a4938a1337907_1024x1024.jpg',
- brand: 'LG',
- stock: 15,
- },
- {
- name: 'Microsoft Surface Laptop 4',
- description: 'Sleek and powerful laptop from Microsoft.',
- price: 1299,
- category: 'computers',
- image: 'https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE4LiXm?ver=45be&q=90&m=6&h=705&w=1253&b=%23FFFFFFFF&f=jpg&o=f&p=140&aim=true',
- brand: 'Microsoft',
- stock: 25,
- },
- {
- name: 'GoPro Hero 10 Black',
- description: 'High-performance action camera for capturing your adventures.',
- price: 499,
- category: 'electronics',
- image: 'https://cdn.vjshop.vn/camera-hanh-dong/gopro/gopro-hero-10/gopro-hero-10-1000x1000.png',
- brand: 'GoPro',
- stock: 50,
- },
- {
- name: 'Bose QuietComfort 45 Headphones',
- description: 'Premium noise-canceling headphones for immersive audio experience.',
- price: 329,
- category: 'electronics',
- image: 'https://cdn.nguyenkimmall.com/images/detailed/848/10054167-tai-nghe-khong-day-bose-quietcomfort-45-den-866724-0100-1.jpg',
- brand: 'Bose',
- stock: 100,
- },
- {
- name: 'iPad Pro 12.9" (2022)',
- description: 'Powerful tablet with M1 chip and stunning Liquid Retina XDR display.',
- price: 1099,
- category: 'electronics',
- image: 'https://cdn2.cellphones.com.vn/x/media/catalog/product/i/p/ipad-pro-13-select-202210_3_3_1_1.png',
- brand: 'Apple',
- stock: 50,
- },
- {
- name: 'Samsung Galaxy S22 Ultra',
- description: 'Samsung\'s latest flagship smartphone with S Pen support.',
- price: 1199,
- category: 'electronics',
- image: 'https://i5.walmartimages.com/seo/Samsung-Galaxy-S22-Ultra-5G-SM-S908U1-256GB-Green-US-Model-Factory-Unlocked-Cell-Phone-Very-Good-Condition_0b4b7166-2688-4e0c-954d-539d5ea29ad9.5946110fe2a2c21cda0b256e2969a555.jpeg',
- brand: 'Samsung',
- stock: 30,
- },
- {
- name: 'Sony A7C',
- description: 'Compact full-frame mirrorless camera with 24MP sensor.',
- price: 1799,
- category: 'electronics',
- image: 'https://cdn.vjshop.vn/may-anh/mirrorless/sony/sony-alpha-a7c/sony-a7c-black-1.jpg',
- brand: 'Sony',
- stock: 10,
- },
- {
- name: 'LG Gram 17" Laptop',
- description: 'Ultra-lightweight laptop with long battery life.',
- price: 1499,
- category: 'computers',
- image: 'https://lapvip.vn/upload/products/original/lg-gram-17-20232-1700187329.jpg',
- brand: 'LG',
- stock: 20,
- },
- {
- name: 'Canon EOS R6',
- description: 'High-performance mirrorless camera with 20MP sensor.',
- price: 2499,
- category: 'electronics',
- image: 'https://cdn.vjshop.vn/may-anh/mirrorless/canon/canon-eos-r6/canon-eos-r6-1-1500x1500.jpg',
- brand: 'Canon',
- stock: 5,
- },
- {
- name: 'Apple AirPods Max',
- description: 'Premium over-ear headphones with high-fidelity audio.',
- price: 549,
- category: 'electronics',
- image: 'https://store.storeimages.cdn-apple.com/8756/as-images.apple.com/is/airpods-max-hero-select-202011_FMT_WHH?wid=607&hei=556&fmt=jpeg&qlt=90&.v=1633623988000',
- brand: 'Apple',
- stock: 50,
- },
- {
- name: 'Dell XPS 13',
- description: 'Ultra-portable laptop with stunning InfinityEdge display.',
- price: 999,
- category: 'computers',
- image: 'https://product.hstatic.net/1000331874/product/dell_xps_13_dc9a366cc90c495b9a3da844f2a08cb9_1024x1024.jpg',
- brand: 'Dell',
- stock: 30,
- },
- {
- name: 'Samsung Galaxy Watch 4',
- description: 'Stylish smartwatch with advanced health tracking features.',
- price: 249,
- category: 'electronics',
- image: 'https://cdn-v2.didongviet.vn/files/media/catalog/product/s/a/samsung-galaxy-watch-4-40mm-likenew-mau-den-didongviet.jpeg',
- brand: 'Samsung',
- stock: 100,
- },
- {
- name: 'Sony WH-1000XM4 Headphones',
- description: 'Premium noise-canceling headphones with long battery life.',
- price: 349,
- category: 'electronics',
- image: 'https://www.sony.com.vn/image/5d02da5df552836db894cead8a68f5f3?fmt=pjpeg&wid=330&bgcolor=FFFFFF&bgc=FFFFFF',
- brand: 'Sony',
- stock: 100,
- }
+ {
+ name: 'iPhone 15 Pro Max',
+ description: "Apple's latest flagship smartphone.",
+ price: 1099,
+ category: 'electronics',
+ image: 'https://cdn.tgdd.vn/Products/Images/42/305658/iphone-15-pro-max-blue-thumbnew-600x600.jpg',
+ brand: 'Apple',
+ stock: 100,
+ },
+ {
+ name: 'MacBook Air M2',
+ description: 'Powerful and lightweight laptop from Apple.',
+ price: 1199,
+ category: 'computers',
+ image: 'https://cdn8.web4s.vn/media/products/mac-air-m2/macbookairm2-midnight%201.jpg',
+ brand: 'Apple',
+ stock: 50,
+ },
+ {
+ name: 'Sony WH-1000XM5 Headphones',
+ description: 'Industry-leading noise-canceling headphones.',
+ price: 399,
+ category: 'electronics',
+ image: 'https://bizweb.dktcdn.net/100/340/129/products/wh1000xm5-midnightblue-2-cuongphanvn.jpg?v=1714306049613',
+ brand: 'Sony',
+ stock: 200,
+ },
+ {
+ name: 'Samsung 65" QLED TV',
+ description: 'Immersive 4K TV experience with QLED technology.',
+ price: 1499,
+ category: 'electronics',
+ image: 'https://cdn.mediamart.vn/images/product/qled-tivi-4k-samsung-65-inch-65q80c-smart-tv_5304e716.png', // Replace with actual image URL
+ brand: 'Samsung',
+ stock: 10,
+ },
+ {
+ name: 'Canon EOS R5',
+ description: 'High-performance mirrorless camera from Canon.',
+ price: 3799,
+ category: 'electronics',
+ image: 'https://i1.adis.ws/i/canon/eos-r5_front_rf24-105mmf4lisusm_square_32c26ad194234d42b3cd9e582a21c99b',
+ brand: 'Canon',
+ stock: 5,
+ },
+ {
+ name: 'Apple Watch Series 7',
+ description: 'Stay connected and healthy with the latest Apple Watch.',
+ price: 399,
+ category: 'electronics',
+ image: 'https://akbroshop.com/wp-content/uploads/2022/08/hinh-aw-s7-xanh.jpg',
+ brand: 'Apple',
+ stock: 100,
+ },
+ {
+ name: 'Dell XPS 15',
+ description: 'Powerful laptop with stunning 4K display.',
+ price: 1799,
+ category: 'computers',
+ image: 'https://minhvu.vn/thumb/dellxps/dellxps159530/dellxps159530cbfbjco_480_360.jpg',
+ brand: 'Dell',
+ stock: 20,
+ },
+ {
+ name: 'Samsung Galaxy Tab S7+',
+ description: 'Premium Android tablet with stunning AMOLED display.',
+ price: 849,
+ category: 'electronics',
+ image: 'https://hanoicomputercdn.com/media/product/60370_may_tinh_bang_samsung_galaxy_tab_s7_plus_128gb_den.png',
+ brand: 'Samsung',
+ stock: 30,
+ },
+ {
+ name: 'Sony A7 IV',
+ description: 'Full-frame mirrorless camera with 33MP sensor.',
+ price: 2499,
+ category: 'electronics',
+ image: 'https://zshop.vn/images/detailed/92/1634812545_1667800.jpg',
+ brand: 'Sony',
+ stock: 10,
+ },
+ {
+ name: 'LG C1 OLED TV',
+ description: 'Stunning OLED TV with great picture quality.',
+ price: 1999,
+ category: 'electronics',
+ image: 'https://product.hstatic.net/200000574527/product/dz-6_ac9672a6534245fcbb1a4938a1337907_1024x1024.jpg',
+ brand: 'LG',
+ stock: 15,
+ },
+ {
+ name: 'Microsoft Surface Laptop 4',
+ description: 'Sleek and powerful laptop from Microsoft.',
+ price: 1299,
+ category: 'computers',
+ image:
+ 'https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE4LiXm?ver=45be&q=90&m=6&h=705&w=1253&b=%23FFFFFFFF&f=jpg&o=f&p=140&aim=true',
+ brand: 'Microsoft',
+ stock: 25,
+ },
+ {
+ name: 'GoPro Hero 10 Black',
+ description: 'High-performance action camera for capturing your adventures.',
+ price: 499,
+ category: 'electronics',
+ image: 'https://cdn.vjshop.vn/camera-hanh-dong/gopro/gopro-hero-10/gopro-hero-10-1000x1000.png',
+ brand: 'GoPro',
+ stock: 50,
+ },
+ {
+ name: 'Bose QuietComfort 45 Headphones',
+ description: 'Premium noise-canceling headphones for immersive audio experience.',
+ price: 329,
+ category: 'electronics',
+ image: 'https://cdn.nguyenkimmall.com/images/detailed/848/10054167-tai-nghe-khong-day-bose-quietcomfort-45-den-866724-0100-1.jpg',
+ brand: 'Bose',
+ stock: 100,
+ },
+ {
+ name: 'iPad Pro 12.9" (2022)',
+ description: 'Powerful tablet with M1 chip and stunning Liquid Retina XDR display.',
+ price: 1099,
+ category: 'electronics',
+ image: 'https://cdn2.cellphones.com.vn/x/media/catalog/product/i/p/ipad-pro-13-select-202210_3_3_1_1.png',
+ brand: 'Apple',
+ stock: 50,
+ },
+ {
+ name: 'Samsung Galaxy S22 Ultra',
+ description: "Samsung's latest flagship smartphone with S Pen support.",
+ price: 1199,
+ category: 'electronics',
+ image:
+ 'https://i5.walmartimages.com/seo/Samsung-Galaxy-S22-Ultra-5G-SM-S908U1-256GB-Green-US-Model-Factory-Unlocked-Cell-Phone-Very-Good-Condition_0b4b7166-2688-4e0c-954d-539d5ea29ad9.5946110fe2a2c21cda0b256e2969a555.jpeg',
+ brand: 'Samsung',
+ stock: 30,
+ },
+ {
+ name: 'Sony A7C',
+ description: 'Compact full-frame mirrorless camera with 24MP sensor.',
+ price: 1799,
+ category: 'electronics',
+ image: 'https://cdn.vjshop.vn/may-anh/mirrorless/sony/sony-alpha-a7c/sony-a7c-black-1.jpg',
+ brand: 'Sony',
+ stock: 10,
+ },
+ {
+ name: 'LG Gram 17" Laptop',
+ description: 'Ultra-lightweight laptop with long battery life.',
+ price: 1499,
+ category: 'computers',
+ image: 'https://lapvip.vn/upload/products/original/lg-gram-17-20232-1700187329.jpg',
+ brand: 'LG',
+ stock: 20,
+ },
+ {
+ name: 'Canon EOS R6',
+ description: 'High-performance mirrorless camera with 20MP sensor.',
+ price: 2499,
+ category: 'electronics',
+ image: 'https://cdn.vjshop.vn/may-anh/mirrorless/canon/canon-eos-r6/canon-eos-r6-1-1500x1500.jpg',
+ brand: 'Canon',
+ stock: 5,
+ },
+ {
+ name: 'Apple AirPods Max',
+ description: 'Premium over-ear headphones with high-fidelity audio.',
+ price: 549,
+ category: 'electronics',
+ image:
+ 'https://store.storeimages.cdn-apple.com/8756/as-images.apple.com/is/airpods-max-hero-select-202011_FMT_WHH?wid=607&hei=556&fmt=jpeg&qlt=90&.v=1633623988000',
+ brand: 'Apple',
+ stock: 50,
+ },
+ {
+ name: 'Dell XPS 13',
+ description: 'Ultra-portable laptop with stunning InfinityEdge display.',
+ price: 999,
+ category: 'computers',
+ image: 'https://product.hstatic.net/1000331874/product/dell_xps_13_dc9a366cc90c495b9a3da844f2a08cb9_1024x1024.jpg',
+ brand: 'Dell',
+ stock: 30,
+ },
+ {
+ name: 'Samsung Galaxy Watch 4',
+ description: 'Stylish smartwatch with advanced health tracking features.',
+ price: 249,
+ category: 'electronics',
+ image: 'https://cdn-v2.didongviet.vn/files/media/catalog/product/s/a/samsung-galaxy-watch-4-40mm-likenew-mau-den-didongviet.jpeg',
+ brand: 'Samsung',
+ stock: 100,
+ },
+ {
+ name: 'Sony WH-1000XM4 Headphones',
+ description: 'Premium noise-canceling headphones with long battery life.',
+ price: 349,
+ category: 'electronics',
+ image: 'https://www.sony.com.vn/image/5d02da5df552836db894cead8a68f5f3?fmt=pjpeg&wid=330&bgcolor=FFFFFF&bgc=FFFFFF',
+ brand: 'Sony',
+ stock: 100,
+ },
];
const seedDB = async () => {
- await Product.deleteMany({});
- await Product.insertMany(productSeeds);
- console.log('Products data seeded successfully!');
+ await Product.deleteMany({});
+ await Product.insertMany(productSeeds);
+ console.log('Products data seeded successfully!');
};
//only run when the "node productSeeds.js dev" command is executed manually
-if(process.argv[2] == "dev") {
- dotenv.config({ path: path.resolve(__dirname, '../.env') });
- mongoose
- .connect(process.env.MONGO_URI, { })
- .then(async() => {
- await seedDB();
- process.exit();
- });
- }
+if (process.argv[2] == 'dev') {
+ dotenv.config({ path: path.resolve(__dirname, '../.env') });
+ mongoose.connect(process.env.MONGO_URI, {}).then(async () => {
+ await seedDB();
+ process.exit();
+ });
+}
module.exports = seedDB;
diff --git a/package-lock.json b/package-lock.json
index 09df00a..15038bc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,13 @@
{
- "name": "ecommerce-fullstack-website",
- "version": "0.1.0",
+ "name": "ecommerce-fullstack-website-frontend",
+ "version": "1.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
- "name": "ecommerce-fullstack-website",
- "version": "0.1.0",
+ "name": "ecommerce-fullstack-website-frontend",
+ "version": "1.1.0",
+ "license": "MIT",
"dependencies": {
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
@@ -22,6 +23,7 @@
"@testing-library/user-event": "^13.5.0",
"axios": "^1.7.2",
"http-proxy-middleware": "^3.0.0",
+ "prettier": "^3.3.3",
"react": "^18.3.1",
"react-credit-cards-2": "^1.0.2",
"react-dom": "^18.3.1",
@@ -15205,6 +15207,20 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/prettier": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
+ "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
"node_modules/pretty-bytes": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
@@ -29665,6 +29681,11 @@
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="
},
+ "prettier": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
+ "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew=="
+ },
"pretty-bytes": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
diff --git a/package.json b/package.json
index 59ed25c..b4cc494 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
"@testing-library/user-event": "^13.5.0",
"axios": "^1.7.2",
"http-proxy-middleware": "^3.0.0",
+ "prettier": "^3.3.3",
"react": "^18.3.1",
"react-credit-cards-2": "^1.0.2",
"react-dom": "^18.3.1",
@@ -40,7 +41,8 @@
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
- "eject": "react-scripts eject"
+ "eject": "react-scripts eject",
+ "format": "prettier --config .prettierrc --write \"setupProxy.js\" \"src/components/*.{html,css,js,jsx,ts,tsx}\" \"src/dev/*.{html,css,js,jsx,ts,tsx}\" \"src/pages/*.{html,css,js,jsx,ts,tsx}\" \"src/*.{html,css,js,jsx,ts,tsx}\" \"backend/*.{html,css,js,jsx,ts,tsx}\" \"backend/seed/*.{html,css,js,jsx,ts,tsx}\" \"backend/routes/*.{html,css,js,jsx,ts,tsx}\" \"backend/docs/*.{html,css,js,jsx,ts,tsx}\" \"backend/config/*.{html,css,js,jsx,ts,tsx}\""
},
"eslintConfig": {
"extends": [
diff --git a/setupProxy.js b/setupProxy.js
index fbc1540..2198671 100644
--- a/setupProxy.js
+++ b/setupProxy.js
@@ -1,11 +1,11 @@
const { createProxyMiddleware } = require('http-proxy-middleware');
-module.exports = function(app) {
- app.use(
- '/api',
- createProxyMiddleware({
- target: 'http://localhost:5000',
- changeOrigin: true,
- })
- );
+module.exports = function (app) {
+ app.use(
+ '/api',
+ createProxyMiddleware({
+ target: 'http://localhost:5000',
+ changeOrigin: true,
+ })
+ );
};
diff --git a/src/App.css b/src/App.css
index ecad11b..8ee55a2 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,93 +1,95 @@
/* General Styles */
body {
- font-family: sans-serif;
- margin: 0;
- padding: 0;
- background-color: #f5f5f5;
+ font-family: sans-serif;
+ margin: 0;
+ padding: 0;
+ background-color: #f5f5f5;
}
.container {
- max-width: 1200px;
- margin: 0 auto;
- padding: 20px;
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 20px;
}
-h1, h2, h3 {
- color: #333;
+h1,
+h2,
+h3 {
+ color: #333;
}
/* Navigation Bar */
.navbar {
- background-color: #2874f0;
- color: white;
- padding: 15px;
+ background-color: #2874f0;
+ color: white;
+ padding: 15px;
}
.navbar ul {
- list-style-type: none;
- margin: 0;
- padding: 0;
- display: flex;
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ display: flex;
}
.navbar li {
- margin-right: 20px;
+ margin-right: 20px;
}
.navbar a {
- color: white;
- text-decoration: none;
+ color: white;
+ text-decoration: none;
}
/* Home Page */
.home {
- text-align: center;
- padding: 50px;
+ text-align: center;
+ padding: 50px;
}
.home h2 {
- font-size: 3rem;
+ font-size: 3rem;
}
/* Shop Page */
.product-grid {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
- gap: 20px;
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ gap: 20px;
}
.product-card {
- border: 1px solid #ddd;
- padding: 20px;
+ border: 1px solid #ddd;
+ padding: 20px;
}
.product-card img {
- max-width: 100%;
- height: auto;
+ max-width: 100%;
+ height: auto;
}
/* Cart Page */
.cart-item {
- display: flex;
- align-items: center;
- margin-bottom: 20px;
+ display: flex;
+ align-items: center;
+ margin-bottom: 20px;
}
.cart-item img {
- width: 80px;
- height: 80px;
- margin-right: 20px;
+ width: 80px;
+ height: 80px;
+ margin-right: 20px;
}
/* Checkout Page */
.checkout {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 20px;
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 20px;
}
/* Order Success Page */
.order-success {
- text-align: center;
- padding: 50px;
+ text-align: center;
+ padding: 50px;
}
diff --git a/src/App.jsx b/src/App.jsx
index c388bb0..3d261ab 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -11,89 +11,69 @@ import OrderSuccess from './pages/OrderSuccess';
import ProductDetails from './pages/ProductDetails';
const theme = createTheme({
- palette: {
- primary: {
- main: '#2874f0',
- },
- secondary: {
- main: '#f50057',
- },
+ palette: {
+ primary: {
+ main: '#2874f0',
},
- typography: {
- fontFamily: 'Roboto, sans-serif',
+ secondary: {
+ main: '#f50057',
},
+ },
+ typography: {
+ fontFamily: 'Roboto, sans-serif',
+ },
});
function App() {
- const [products, setProducts] = React.useState([]);
- const [cart, setCart] = React.useState([]);
- const [loading, setLoading] = React.useState(true);
+ const [products, setProducts] = React.useState([]);
+ const [cart, setCart] = React.useState([]);
+ const [loading, setLoading] = React.useState(true);
- React.useEffect(() => {
- const fetchProducts = async () => {
- try {
- // Be sure to replace the endpoint if your API (backend server) is running on a different port
- // This is the default port for the Express server - port 5000
- const response = await fetch('http://localhost:5000/api/products');
- const data = await response.json();
- setProducts(data);
- }
- catch (error) {
- console.error('Error fetching products:', error);
- }
- finally {
- setLoading(false);
- }
- };
+ React.useEffect(() => {
+ const fetchProducts = async () => {
+ try {
+ // Be sure to replace the endpoint if your API (backend server) is running on a different port
+ // This is the default port for the Express server - port 5000
+ const response = await fetch('http://localhost:5000/api/products');
+ const data = await response.json();
+ setProducts(data);
+ } catch (error) {
+ console.error('Error fetching products:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
- fetchProducts();
- }, []);
+ fetchProducts();
+ }, []);
- const addToCart = (product) => {
- setCart([...cart, product]);
- };
+ const addToCart = product => {
+ setCart([...cart, product]);
+ };
- return (
-