diff --git a/package.json b/package.json index 9b0c7fa..9a590be 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "csv-parser": "^3.0.0", "dotenv": "^16.0.3", "express": "^4.22.2", + "express-validator": "^7.3.2", "jsonwebtoken": "^9.0.3", "node-pg": "^1.0.1", "p-limit": "^7.3.0", diff --git a/src/app.js b/src/app.js index c62d529..598f2a8 100644 --- a/src/app.js +++ b/src/app.js @@ -5,6 +5,8 @@ import healthCheckRoutes from './routes/healthcheck' import authRoutes from './routes/auth' import userRoutes from './routes/users' import roleRoutes from './routes/roles' +import locationRoutes from './routes/locations' +import imageRoutes from './routes/images' const app = express() const port = process.env.PORT || 3000 @@ -19,6 +21,8 @@ app.use('/healthcheck', healthCheckRoutes) app.use('/auth', authRoutes) app.use('/users', userRoutes) app.use('/roles', roleRoutes) +app.use('/locations', locationRoutes) +app.use('/images', imageRoutes) // Default Route (Catch-all for undefined routes) app.use((req, res, next) => { diff --git a/src/routes/images/index.js b/src/routes/images/index.js new file mode 100644 index 0000000..a0b59d5 --- /dev/null +++ b/src/routes/images/index.js @@ -0,0 +1,113 @@ +import express from 'express' +import { check, validationResult } from 'express-validator/check' +import { Pool } from 'pg' +import { database } from '../../config' + +const router = express.Router() + +// Create a connection pool to the database +const pool = new Pool(database) + +// CREATE AN IMAGE +router.post('/', [ + check('file').isString(), + check('image').isBase64() +], async (req, res) => { + try { + const errors = validationResult(req) + if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() }) + + const { file, image } = req.body + + const client = await pool.connect() + const result = await client.query('INSERT INTO images (file, image, created_at, updated_at) VALUES ($1, $2, NOW(), NOW()) RETURNING *', [file, image]) + client.release() + + return res.status(201).json(result.rows[0]) + } catch (err) { + console.error(err.stack) + return res.status(500).json({ error: 'Server error' }) + } +}) + +// READ AN IMAGE +router.get('/:id', async (req, res) => { + try { + const { id } = req.params + + const client = await pool.connect() + const result = await client.query('SELECT * FROM images WHERE id = $1', [id]) + client.release() + + if (result.rows.length === 0) return res.status(404).json({ error: 'Image not found' }) + + return res.status(200).json(result.rows[0]) + } catch (err) { + console.error(err.stack) + return res.status(500).json({ error: 'Server error' }) + } +}) + +// UPDATE AN IMAGE +router.put('/:id', [ + check('file').optional().isString(), + check('image').optional().isBase64() +], async (req, res) => { + try { + const errors = validationResult(req) + if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() }) + + const { id } = req.params + const { file, image } = req.body + + const client = await pool.connect() + let query = 'UPDATE images SET' + const values = [] + + if (file) { + query += ' file = $1,' + values.push(file) + } + + if (image) { + query += ' image = $2,' + values.push(image) + } + + // Remove trailing comma and space from query string + query = query.slice(0, -1) + + query += ', updated_at = NOW() WHERE id = $3 RETURNING *' + values.push(id) + + const result = await client.query(query, values) + client.release() + + if (result.rows.length === 0) return res.status(404).json({ error: 'Image not found' }) + + return res.status(200).json(result.rows[0]) + } catch (err) { + console.error(err.stack) + return res.status(500).json({ error: 'Server error' }) + } +}) + +// DELETE AN IMAGE +router.delete('/:id', async (req, res) => { + try { + const { id } = req.params + + const client = await pool.connect() + const result = await client.query('DELETE FROM images WHERE id = $1 RETURNING *', [id]) + client.release() + + if (result.rows.length === 0) return res.status(404).json({ error: 'Image not found' }) + + return res.status(200).json(result.rows[0]) + } catch (err) { + console.error(err.stack) + return res.status(500).json({ error: 'Server error' }) + } +}) + +export default router diff --git a/src/routes/locations/index.js b/src/routes/locations/index.js new file mode 100644 index 0000000..774f668 --- /dev/null +++ b/src/routes/locations/index.js @@ -0,0 +1,91 @@ +import express from 'express' +import { check, validationResult } from 'express-validator/check' +import { Pool } from 'pg' +import { database } from '../../config' + +const router = express.Router() + +// Create a connection pool to the database +const pool = new Pool(database) + +// Create a new location +router.post( + '/', + [check('name', 'Name is required').not().isEmpty()], + async (req, res) => { + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(400).json({ errors: errors.array() }) + } + try { + const { name } = req.body + await pool.query( + 'INSERT INTO locations (name, created_at, updated_at) VALUES ($1, NOW(), NOW())', + [name] + ) + res.send({ message: 'Location created' }) + } catch (err) { + console.error(err.message) + res.status(500).send('Server error') + } + } +) + +// Get all locations +router.get('/', async (req, res) => { + try { + const result = await pool.query('SELECT * FROM locations') + res.send(result.rows) + } catch (err) { + console.error(err.message) + res.status(500).send('Server error') + } +}) + +// Get a single location by ID +router.get('/:id', async (req, res) => { + try { + const result = await pool.query('SELECT * FROM locations WHERE id = $1', [req.params.id]) + if (result.rows.length === 0) return res.status(404).send('Location not found') + res.send(result.rows[0]) + } catch (err) { + console.error(err.message) + res.status(500).send('Server error') + } +}) + +// Update a location +router.put( + '/:id', + [check('name', 'Name is required').not().isEmpty()], + async (req, res) => { + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(400).json({ errors: errors.array() }) + } + try { + const { name } = req.body + await pool.query( + 'UPDATE locations SET name = $1, updated_at = NOW() WHERE id = $2', + [name, req.params.id] + ) + res.send({ message: 'Location updated' }) + } catch (err) { + console.error(err.message) + res.status(500).send('Server error') + } + } +) + +// Delete a location +router.delete('/:id', async (req, res) => { + try { + await pool.query('DELETE FROM locations WHERE id = $1', [req.params.id]) + res.send({ message: 'Location deleted' }) + } catch (err) { + console.error(err.message) + res.status(500).send('Server error') + } +}) + +export default router