diff --git a/admin.html b/admin.html index ecebe80..62a866f 100644 --- a/admin.html +++ b/admin.html @@ -2,38 +2,11 @@ + - Admin Box Editor - + Redirecting... -
-
-
-
-

Administrator box editor

-

Change the price, picture, and description for all 8 boxes.

-
- Back to home -
- -
- - - -
- -

Enter the admin code to edit box details.

- - - - -
-
- - +

Redirecting to Box Data Editor...

- \ No newline at end of file + diff --git a/backend/data/boxes.json b/backend/data/boxes.json new file mode 100644 index 0000000..afe86c6 --- /dev/null +++ b/backend/data/boxes.json @@ -0,0 +1,58 @@ +[ + { + "id": "box-1", + "name": "Small Shipping Box", + "price": 9.99, + "image": "images/boxes/box-1.svg", + "description": "Compact corrugated box for light parts, samples, and small product shipments." + }, + { + "id": "box-2", + "name": "Medium Mailer Box", + "price": 12.5, + "image": "images/boxes/box-2.svg", + "description": "Strong everyday mailer with extra room for inserts, labels, and protective padding." + }, + { + "id": "box-3", + "name": "Heavy Duty Carton", + "price": 15.25, + "image": "images/boxes/box-3.svg", + "description": "Durable double-wall carton built for heavier items and warehouse handling." + }, + { + "id": "box-4", + "name": "Retail Display Box", + "price": 18, + "image": "images/boxes/box-4.svg", + "description": "Clean presentation box designed for retail shelves, kits, and branded packaging." + }, + { + "id": "box-5", + "name": "Long Parts Box", + "price": 14.75, + "image": "images/boxes/box-5.svg", + "description": "Extended-length box for narrow components, rods, trims, and specialty parts." + }, + { + "id": "box-6", + "name": "Deep Storage Box", + "price": 16.5, + "image": "images/boxes/box-6.svg", + "description": "Deep format storage box for bulk inventory, stacked packing, and backroom use." + }, + { + "id": "box-7", + "name": "Flat Pack Box", + "price": 11.95, + "image": "images/boxes/box-7.svg", + "description": "Low-profile box for folded materials, manuals, labels, and flat-pack assemblies." + }, + { + "id": "box-8", + "name": "Large Bulk Box", + "price": 22, + "image": "images/boxes/box-8.svg", + "description": "Large-capacity box for bundled products, bulk orders, and industrial shipments." + } +] \ No newline at end of file diff --git a/backend/lib/boxesStore.js b/backend/lib/boxesStore.js new file mode 100644 index 0000000..c7958d3 --- /dev/null +++ b/backend/lib/boxesStore.js @@ -0,0 +1,62 @@ +const fs = require('fs'); +const path = require('path'); + +const BOXES_FILE = path.join(__dirname, '..', 'data', 'boxes.json'); + +const DEFAULT_BOXES = Array.from({ length: 8 }, (_, index) => ({ + id: `box-${index + 1}`, + name: `Box ${index + 1}`, + price: 0, + image: '', + description: '', +})); + +function ensureBoxesFile() { + const dir = path.dirname(BOXES_FILE); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + + if (!fs.existsSync(BOXES_FILE)) { + fs.writeFileSync(BOXES_FILE, JSON.stringify(DEFAULT_BOXES, null, 2)); + } +} + +function normalizeBox(box = {}, index = 0) { + return { + id: box.id || `box-${index + 1}`, + name: String(box.name || `Box ${index + 1}`).trim(), + price: Number(box.price || 0), + image: String(box.image || '').trim(), + description: String(box.description || '').trim(), + }; +} + +function readBoxes() { + ensureBoxesFile(); + try { + const raw = fs.readFileSync(BOXES_FILE, 'utf8'); + const parsed = JSON.parse(raw); + if (!Array.isArray(parsed)) { + return DEFAULT_BOXES.map(normalizeBox); + } + const padded = Array.from({ length: 8 }, (_, index) => normalizeBox(parsed[index] || {}, index)); + return padded; + } catch (error) { + console.error('Error reading boxes file:', error); + return DEFAULT_BOXES.map(normalizeBox); + } +} + +function writeBoxes(boxes = []) { + ensureBoxesFile(); + const normalized = Array.from({ length: 8 }, (_, index) => normalizeBox(boxes[index] || {}, index)); + fs.writeFileSync(BOXES_FILE, JSON.stringify(normalized, null, 2)); + return normalized; +} + +module.exports = { + BOXES_FILE, + readBoxes, + writeBoxes, +}; diff --git a/backend/routes/boxRoutes.js b/backend/routes/boxRoutes.js new file mode 100644 index 0000000..bcd5a2f --- /dev/null +++ b/backend/routes/boxRoutes.js @@ -0,0 +1,38 @@ +const express = require('express'); +const { readBoxes, writeBoxes } = require('../lib/boxesStore'); + +const router = express.Router(); +const EDITOR_CODE = process.env.BOX_EDITOR_CODE || process.env.ADMIN_CODE || '1234'; + +function requireEditorCode(req, res, next) { + const code = req.headers['x-editor-code'] || req.body.editorCode || req.query.editorCode; + if (code !== EDITOR_CODE) { + return res.status(401).json({ success: false, message: 'Invalid editor code' }); + } + next(); +} + +router.get('/', (req, res) => { + res.json({ + success: true, + boxes: readBoxes(), + file: 'backend/data/boxes.json', + }); +}); + +router.put('/', requireEditorCode, (req, res) => { + const boxes = Array.isArray(req.body.boxes) ? req.body.boxes : []; + if (boxes.length !== 8) { + return res.status(400).json({ success: false, message: 'Exactly 8 boxes are required.' }); + } + + const savedBoxes = writeBoxes(boxes); + res.json({ + success: true, + message: 'Box data saved successfully.', + boxes: savedBoxes, + file: 'backend/data/boxes.json', + }); +}); + +module.exports = router; diff --git a/backend/server.js b/backend/server.js index d1b4daf..b081a8a 100644 --- a/backend/server.js +++ b/backend/server.js @@ -7,7 +7,6 @@ require('dotenv').config(); const app = express(); app.set('trust proxy', true); -// Middleware app.use(cors()); app.use(express.json()); app.use(express.urlencoded({ extended: true })); @@ -58,39 +57,28 @@ app.post(['/.wf_graphql/apollo', '/.wf_graphql/usys/apollo'], (req, res) => { }); }); -// Serve static files from the root directory -app.use(express.static(path.join(__dirname, '..'))); +app.use('/api/boxes', require('./routes/boxRoutes')); +app.use('/api/auth', require('./routes/authRoutes')); +app.use('/api/users', require('./routes/userRoutes')); +app.use('/api/products', require('./routes/productRoutes')); +app.use('/api/cart', require('./routes/cartRoutes')); +app.use('/api/orders', require('./routes/orderRoutes')); -// Basic route -app.get('/', (req, res) => { - res.json({ message: 'Welcome to Mom\'s Web API' }); -}); - -// Health check app.get('/api/health', (req, res) => { res.json({ status: 'Server is running' }); }); -// Routes -app.use('/api/auth', require('./routes/authRoutes')); -app.use('/api/users', require('./routes/userRoutes')); -app.use('/api/products', require('./routes/productRoutes')); -app.use('/api/admin', require('./routes/adminRoutes')); -app.use('/api/cart', require('./routes/cartRoutes')); -app.use('/api/orders', require('./routes/orderRoutes')); +app.use(express.static(path.join(__dirname, '..'))); -// Error handling middleware app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ message: 'Internal Server Error' }); }); -// 404 handler app.use((req, res) => { res.status(404).json({ message: 'Route not found' }); }); -// Start server const PORT = process.env.PORT || 5000; const HOST = process.env.HOST || '0.0.0.0'; app.listen(PORT, HOST, () => { diff --git a/box-editor.html b/box-editor.html new file mode 100644 index 0000000..2648080 --- /dev/null +++ b/box-editor.html @@ -0,0 +1,39 @@ + + + + + + Box Data Editor + + + +
+
+
+
+

Box data editor

+

Update the name, price, picture, and description for all 8 boxes.

+
+ View boxes +
+ +
+ + + +
+ +

Tip: you can also edit backend/data/boxes.json directly in the codebase.

+ + + + +
+
+ + + + diff --git a/company.html b/company.html index 914a756..c817abf 100644 --- a/company.html +++ b/company.html @@ -65,13 +65,7 @@ Contact - - Admin - - - Login / Register -
+ + + + + + + BOX 1 + \ No newline at end of file diff --git a/images/boxes/box-2.svg b/images/boxes/box-2.svg new file mode 100644 index 0000000..6ff0c20 --- /dev/null +++ b/images/boxes/box-2.svg @@ -0,0 +1,9 @@ + + + + + + + + BOX 2 + \ No newline at end of file diff --git a/images/boxes/box-3.svg b/images/boxes/box-3.svg new file mode 100644 index 0000000..133cfbd --- /dev/null +++ b/images/boxes/box-3.svg @@ -0,0 +1,9 @@ + + + + + + + + BOX 3 + \ No newline at end of file diff --git a/images/boxes/box-4.svg b/images/boxes/box-4.svg new file mode 100644 index 0000000..505a190 --- /dev/null +++ b/images/boxes/box-4.svg @@ -0,0 +1,9 @@ + + + + + + + + BOX 4 + \ No newline at end of file diff --git a/images/boxes/box-5.svg b/images/boxes/box-5.svg new file mode 100644 index 0000000..a94f0cd --- /dev/null +++ b/images/boxes/box-5.svg @@ -0,0 +1,9 @@ + + + + + + + + BOX 5 + \ No newline at end of file diff --git a/images/boxes/box-6.svg b/images/boxes/box-6.svg new file mode 100644 index 0000000..c9d4551 --- /dev/null +++ b/images/boxes/box-6.svg @@ -0,0 +1,9 @@ + + + + + + + + BOX 6 + \ No newline at end of file diff --git a/images/boxes/box-7.svg b/images/boxes/box-7.svg new file mode 100644 index 0000000..613d30c --- /dev/null +++ b/images/boxes/box-7.svg @@ -0,0 +1,9 @@ + + + + + + + + BOX 7 + \ No newline at end of file diff --git a/images/boxes/box-8.svg b/images/boxes/box-8.svg new file mode 100644 index 0000000..e218eb7 --- /dev/null +++ b/images/boxes/box-8.svg @@ -0,0 +1,9 @@ + + + + + + + + BOX 8 + \ No newline at end of file diff --git a/index.html b/index.html index a86fbaf..e990c8b 100644 --- a/index.html +++ b/index.html @@ -70,13 +70,7 @@ Contact - - Admin - - - Login / Register -
- - +

This page is no longer used. Return to Home.

diff --git a/order.html b/order.html index f162e1e..c9d3f53 100644 --- a/order.html +++ b/order.html @@ -68,13 +68,7 @@ Contact - - Admin - - - Login / Register -
- -