From 5baa5df27ed0152d366012b82c27fac79fe1332b Mon Sep 17 00:00:00 2001 From: ElhamFadel Date: Fri, 29 Oct 2021 20:01:18 +0300 Subject: [PATCH 01/36] put agents --- server/controllers/users/index.js | 3 +- server/controllers/users/putAgent.js | 41 ++++++++++++++++++++++++++++ server/database/quieres/index.js | 3 +- server/database/quieres/putUser.js | 1 + 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 server/controllers/users/putAgent.js create mode 100644 server/database/quieres/putUser.js diff --git a/server/controllers/users/index.js b/server/controllers/users/index.js index 79a3394..d1dd6d8 100644 --- a/server/controllers/users/index.js +++ b/server/controllers/users/index.js @@ -1,4 +1,5 @@ const userEstateshandler = require('./userEstates'); const getAllUsers = require('./getAllUsers'); +const putAgent = require('./putAgent'); -module.exports = { getAllUsers, userEstateshandler }; +module.exports = { getAllUsers, userEstateshandler, putAgent }; diff --git a/server/controllers/users/putAgent.js b/server/controllers/users/putAgent.js new file mode 100644 index 0000000..ba72284 --- /dev/null +++ b/server/controllers/users/putAgent.js @@ -0,0 +1,41 @@ +const { putUser } = require('../../database/quieres'); +const studentSchema = require('../../utils/validation/signUpSchema.js '); + +module.exports = async (req, res, next) => { + try { + const { studentId } = req.params; + const data = await studentSchema.validate( + { ...req.body, studentId }, + { abortEarly: false }, + ); + const result = await putStudent(data); + if (result.rowCount === 1) { + res.json({ + StatusCode: 200, + data: { + message: "Student's data updated successfully", + }, + }); + } else { + res.status(404).json({ + StatusCode: 404, + data: { + message: 'There is no student for this id', + }, + }); + } + } catch (err) { + if (err.errors) { + res.status(400).json({ statusCode: 400, data: { message: err.errors } }); + } else if (err.detail) { + res.status(409).json({ + statusCode: 409, + data: { + message: err.detail, + }, + }); + } else { + next(err); + } + } +}; diff --git a/server/database/quieres/index.js b/server/database/quieres/index.js index 386595b..381d220 100644 --- a/server/database/quieres/index.js +++ b/server/database/quieres/index.js @@ -1,8 +1,9 @@ const userEstatesQuery = require('./userEstatesQuiery'); const getAllUsersQuery = require('./getAllUsersQuery'); +const putUser = require('./putUser'); module.exports = { getAllUsersQuery, userEstatesQuery, - + putUser, }; diff --git a/server/database/quieres/putUser.js b/server/database/quieres/putUser.js new file mode 100644 index 0000000..13880fb --- /dev/null +++ b/server/database/quieres/putUser.js @@ -0,0 +1 @@ +const connection = require('../config/connection'); From 8b0d70b8954a6350d90bb0a67238a7421655cf7c Mon Sep 17 00:00:00 2001 From: ElhamFadel Date: Sat, 30 Oct 2021 12:27:43 +0300 Subject: [PATCH 02/36] edit user --- server/controllers/users/putAgent.js | 8 ++++---- server/database/quieres/index.js | 4 ++-- server/database/quieres/{putUser.js => putAgent.js} | 0 server/utils/validation/editAgentSchema.js | 8 ++++++++ 4 files changed, 14 insertions(+), 6 deletions(-) rename server/database/quieres/{putUser.js => putAgent.js} (100%) create mode 100644 server/utils/validation/editAgentSchema.js diff --git a/server/controllers/users/putAgent.js b/server/controllers/users/putAgent.js index ba72284..e65ccb6 100644 --- a/server/controllers/users/putAgent.js +++ b/server/controllers/users/putAgent.js @@ -1,10 +1,10 @@ -const { putUser } = require('../../database/quieres'); -const studentSchema = require('../../utils/validation/signUpSchema.js '); +const { putAgent } = require('../../database/quieres'); +const agentSchema = require('../../utils/validation/agentSchema'); module.exports = async (req, res, next) => { try { - const { studentId } = req.params; - const data = await studentSchema.validate( + const { agentId } = req.params; + const data = await agentSchema.validate( { ...req.body, studentId }, { abortEarly: false }, ); diff --git a/server/database/quieres/index.js b/server/database/quieres/index.js index 381d220..d09a2e6 100644 --- a/server/database/quieres/index.js +++ b/server/database/quieres/index.js @@ -1,9 +1,9 @@ const userEstatesQuery = require('./userEstatesQuiery'); const getAllUsersQuery = require('./getAllUsersQuery'); -const putUser = require('./putUser'); +const putAgent = require('./putAgent'); module.exports = { getAllUsersQuery, userEstatesQuery, - putUser, + putAgent, }; diff --git a/server/database/quieres/putUser.js b/server/database/quieres/putAgent.js similarity index 100% rename from server/database/quieres/putUser.js rename to server/database/quieres/putAgent.js diff --git a/server/utils/validation/editAgentSchema.js b/server/utils/validation/editAgentSchema.js new file mode 100644 index 0000000..6698b25 --- /dev/null +++ b/server/utils/validation/editAgentSchema.js @@ -0,0 +1,8 @@ +const joi = require('joi'); + +module.exports = joi.object({ + name: joi.string().required(), + email: joi.string().email().required(), + phone: joi.string().length(10).required(), + avater: joi.string(), +}); From 6b1142ae097293fdceda7a712f3a7f634d25d008 Mon Sep 17 00:00:00 2001 From: ElhamFadel Date: Sun, 31 Oct 2021 14:10:16 +0300 Subject: [PATCH 03/36] edit user #10 --- server/controllers/users/putAgent.js | 33 +--------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/server/controllers/users/putAgent.js b/server/controllers/users/putAgent.js index e65ccb6..955a150 100644 --- a/server/controllers/users/putAgent.js +++ b/server/controllers/users/putAgent.js @@ -4,38 +4,7 @@ const agentSchema = require('../../utils/validation/agentSchema'); module.exports = async (req, res, next) => { try { const { agentId } = req.params; - const data = await agentSchema.validate( - { ...req.body, studentId }, - { abortEarly: false }, - ); - const result = await putStudent(data); - if (result.rowCount === 1) { - res.json({ - StatusCode: 200, - data: { - message: "Student's data updated successfully", - }, - }); - } else { - res.status(404).json({ - StatusCode: 404, - data: { - message: 'There is no student for this id', - }, - }); - } } catch (err) { - if (err.errors) { - res.status(400).json({ statusCode: 400, data: { message: err.errors } }); - } else if (err.detail) { - res.status(409).json({ - statusCode: 409, - data: { - message: err.detail, - }, - }); - } else { - next(err); - } + next(err); } }; From d0a79a5152d4b98c7f10e0d073821832acebd17f Mon Sep 17 00:00:00 2001 From: ElhamFadel Date: Sun, 31 Oct 2021 14:27:33 +0300 Subject: [PATCH 04/36] query for update #10 --- server/database/quieres/putAgent.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/database/quieres/putAgent.js b/server/database/quieres/putAgent.js index 13880fb..119af5c 100644 --- a/server/database/quieres/putAgent.js +++ b/server/database/quieres/putAgent.js @@ -1 +1,5 @@ const connection = require('../config/connection'); + +module.exports = ({ + agentId, name, email, phone, avater, +}) => connection.query('UPDATE agent SET name=$1,email=$2,phone=$3,avater=$3 WHERE id=$4', [name, email, phone, avater, agentId]); From 9e9e1e8bf7405bf9fde60d02773455b727f03fb3 Mon Sep 17 00:00:00 2001 From: ElhamFadel Date: Sun, 31 Oct 2021 15:47:25 +0300 Subject: [PATCH 05/36] controller for update agent #10 --- server/controllers/index.js | 5 ++--- server/controllers/users/putAgent.js | 16 ++++++++++++++-- server/database/config/connection.js | 2 +- server/database/quieres/putAgent.js | 4 ++-- server/routes/estate.js | 2 +- server/routes/index.js | 2 +- server/routes/users.js | 5 ++++- server/utils/validation/editAgentSchema.js | 5 +++-- 8 files changed, 28 insertions(+), 13 deletions(-) diff --git a/server/controllers/index.js b/server/controllers/index.js index c0d573e..e38f0db 100644 --- a/server/controllers/index.js +++ b/server/controllers/index.js @@ -1,8 +1,7 @@ -const { userEstateshandler } = require('./users'); -const getAllUsers = require('./users/getAllUsers'); +const { userEstateshandler, putAgent, getAllUsers } = require('./users'); const { deleteEstate } = require('./estates'); const logout = require('./logout'); module.exports = { - getAllUsers, userEstateshandler, logout, deleteEstate, + getAllUsers, userEstateshandler, logout, deleteEstate, putAgent, }; diff --git a/server/controllers/users/putAgent.js b/server/controllers/users/putAgent.js index 955a150..a405276 100644 --- a/server/controllers/users/putAgent.js +++ b/server/controllers/users/putAgent.js @@ -1,9 +1,21 @@ const { putAgent } = require('../../database/quieres'); -const agentSchema = require('../../utils/validation/agentSchema'); +const editAgentSchema = require('../../utils/validation/editAgentSchema'); module.exports = async (req, res, next) => { try { - const { agentId } = req.params; + const { userId } = req.params; + const { error, value } = await editAgentSchema.validate({ ...req.body, userId }); + if (error) return res.status(400).json({ message: error.details[0].message }); + const { rowCount } = await putAgent(value); + if (rowCount === 1) { + res.status(200).json({ + message: "Agent's data updated successfully", + }); + } else { + res.status(404).json({ + message: 'There\'s no Agent, put correct id', + }); + } } catch (err) { next(err); } diff --git a/server/database/config/connection.js b/server/database/config/connection.js index 2e4a695..977118a 100644 --- a/server/database/config/connection.js +++ b/server/database/config/connection.js @@ -21,6 +21,6 @@ switch (NODE_ENV) { const options = { connectionString: dbUrl, - ssl: { rejectUnauthorized: false }, + ssl: false, }; module.exports = new Pool(options); diff --git a/server/database/quieres/putAgent.js b/server/database/quieres/putAgent.js index 119af5c..69bb01f 100644 --- a/server/database/quieres/putAgent.js +++ b/server/database/quieres/putAgent.js @@ -1,5 +1,5 @@ const connection = require('../config/connection'); module.exports = ({ - agentId, name, email, phone, avater, -}) => connection.query('UPDATE agent SET name=$1,email=$2,phone=$3,avater=$3 WHERE id=$4', [name, email, phone, avater, agentId]); + userId, username, email, phone, avater = '', +}) => connection.query('UPDATE agents SET name=$1,email=$2,phone=$3,avater=$4 WHERE id=$5', [username, email, phone, avater, userId]); diff --git a/server/routes/estate.js b/server/routes/estate.js index aecdd61..db7f64d 100644 --- a/server/routes/estate.js +++ b/server/routes/estate.js @@ -2,5 +2,5 @@ const router = require('express').Router(); const { isAuth, isAdmin } = require('../middleware'); const { deleteEstate } = require('../controllers'); -router.delete('/:estateId', isAuth, isAdmin, deleteEstate); +// router.delete('/:estateId', isAuth, isAdmin, deleteEstate); module.exports = router; diff --git a/server/routes/index.js b/server/routes/index.js index 152b866..f041524 100644 --- a/server/routes/index.js +++ b/server/routes/index.js @@ -4,7 +4,7 @@ const estate = require('./estate'); const users = require('./users'); router.use('/estate', estate); -router.get('/users', users); +router.use('/users', users); router.get('/logout', logout); module.exports = router; diff --git a/server/routes/users.js b/server/routes/users.js index e93c396..0b886a4 100644 --- a/server/routes/users.js +++ b/server/routes/users.js @@ -1,11 +1,14 @@ const router = require('express').Router(); -const { userEstateshandler, getAllUsers, logout } = require('../controllers'); +const { + userEstateshandler, getAllUsers, logout, putAgent, +} = require('../controllers'); const estate = require('./estate'); const signup = require('../controllers/users/signup'); router.use('/estate', estate); router.post('/signup', signup); router.get('/:userId/estates', userEstateshandler); +router.put('/:userId', putAgent); router.get('/', getAllUsers); module.exports = router; diff --git a/server/utils/validation/editAgentSchema.js b/server/utils/validation/editAgentSchema.js index 6698b25..c404d63 100644 --- a/server/utils/validation/editAgentSchema.js +++ b/server/utils/validation/editAgentSchema.js @@ -1,8 +1,9 @@ const joi = require('joi'); module.exports = joi.object({ - name: joi.string().required(), + username: joi.string().required(), email: joi.string().email().required(), - phone: joi.string().length(10).required(), + phone: joi.string().min(9).required(), avater: joi.string(), + userId: joi.number().min(1).required(), }); From 5a6cab3478475f0e11a755ac7f501c77b7f62482 Mon Sep 17 00:00:00 2001 From: muhammadharoun Date: Sun, 31 Oct 2021 16:55:47 +0200 Subject: [PATCH 06/36] sign up as admin --- server/controllers/admins/signupAdmin.js | 24 ++++++++++++++++++++++++ server/utils/validation/adminSchema.js | 7 +++++++ 2 files changed, 31 insertions(+) create mode 100644 server/controllers/admins/signupAdmin.js create mode 100644 server/utils/validation/adminSchema.js diff --git a/server/controllers/admins/signupAdmin.js b/server/controllers/admins/signupAdmin.js new file mode 100644 index 0000000..23f864a --- /dev/null +++ b/server/controllers/admins/signupAdmin.js @@ -0,0 +1,24 @@ +const { hash } = require('bcrypt'); +const adminSchema = require('../../utils/validation/adminSchema'); +const signUpAdminQuery = require('../../database/quieres'); +const { signToken } = require('../../utils'); + +module.exports = async (req, res, next) => { + try { + const { + error, value: { + password, email, username, + }, + } = adminSchema.validate(req.body); + if (error) return res.status(400).json({ message: error.details[0].message }); + const hasedPasword = await hash(password, 10); + await signUpAdminQuery(username, hasedPasword, email); + const token = await signToken(email, username); + return res.status(201).cookie('token', token).json({ message: 'user created' }); + } catch (err) { + if (err.code === '23505') { + return res.status(400).json({ message: 'The user is already exists' }); + } + return next(err); + } +}; diff --git a/server/utils/validation/adminSchema.js b/server/utils/validation/adminSchema.js new file mode 100644 index 0000000..aa80037 --- /dev/null +++ b/server/utils/validation/adminSchema.js @@ -0,0 +1,7 @@ +const joi = require('joi'); + +module.exports = joi.object({ + username: joi.string().required(), + email: joi.string().email().required(), + password: joi.string().min(5).required(), +}); From 4a4a5d1f25da4f6237384d57de100b2284f204df Mon Sep 17 00:00:00 2001 From: mohammedsalah7 Date: Sun, 31 Oct 2021 16:58:40 +0200 Subject: [PATCH 07/36] create end point to login admin #69 --- server/controllers/admins/index.js | 5 +++++ server/controllers/admins/login.js | 35 ++++++++++++++++++++++++++++++ server/controllers/index.js | 4 +++- server/routes/auth.js | 3 ++- server/routes/users.js | 2 +- server/test/index.test.js | 24 ++++++++++++++++++++ 6 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 server/controllers/admins/login.js diff --git a/server/controllers/admins/index.js b/server/controllers/admins/index.js index e69de29..558317b 100644 --- a/server/controllers/admins/index.js +++ b/server/controllers/admins/index.js @@ -0,0 +1,5 @@ +const adminLogin = require('./login'); + +module.exports = { + adminLogin, +}; diff --git a/server/controllers/admins/login.js b/server/controllers/admins/login.js new file mode 100644 index 0000000..8c8742b --- /dev/null +++ b/server/controllers/admins/login.js @@ -0,0 +1,35 @@ +/* eslint-disable consistent-return */ +const bcrypt = require('bcrypt'); +const { loginSchema } = require('../../utils/validation/loginSchema'); +const { checkAdminQuery } = require('../../database/quieres'); +const { signToken } = require('../../utils'); + +const adminLogin = async (req, res, next) => { + try { + const { email, password } = req.body; + await loginSchema.validateAsync(req.body); + + const { rows } = await checkAdminQuery(email); + + if (!rows.length) { + return res.status(400).json({ message: 'Invalid email or password' }); + } + + const compared = await bcrypt.compare(password, rows[0].password); + if (!compared) { + return res.status(400).json({ message: 'Invalid email or password' }); + } + const token = await signToken(email, rows[0].id); + return res.cookie('token', token).json({ message: 'You are Logged Successfully' }); + } catch (err) { + if (err.details) { + res.status(400).json({ + message: err.details[0].message, + }); + } else { + return next(err); + } + } +}; + +module.exports = adminLogin; diff --git a/server/controllers/index.js b/server/controllers/index.js index aeaa25e..9839b13 100644 --- a/server/controllers/index.js +++ b/server/controllers/index.js @@ -2,7 +2,9 @@ const { userEstateshandler, login } = require('./users'); const getAllUsers = require('./users/getAllUsers'); const { editEstate, deleteEstate } = require('./estates'); const logout = require('./logout'); +const adminLogin = require('./admins'); module.exports = { - getAllUsers, userEstateshandler, logout, login, deleteEstate, editEstate, + getAllUsers, userEstateshandler, logout, login, deleteEstate, editEstate, adminLogin, + }; diff --git a/server/routes/auth.js b/server/routes/auth.js index ad9201b..f9fc0fb 100644 --- a/server/routes/auth.js +++ b/server/routes/auth.js @@ -1,7 +1,8 @@ const router = require('express').Router(); -const { logout, login } = require('../controllers'); +const { logout, login, adminLogin } = require('../controllers'); router.get('/logout', logout); router.post('/login', login); +router.post('/adminLogin', adminLogin); module.exports = router; diff --git a/server/routes/users.js b/server/routes/users.js index e93c396..70aaffa 100644 --- a/server/routes/users.js +++ b/server/routes/users.js @@ -1,5 +1,5 @@ const router = require('express').Router(); -const { userEstateshandler, getAllUsers, logout } = require('../controllers'); +const { userEstateshandler, getAllUsers } = require('../controllers'); const estate = require('./estate'); const signup = require('../controllers/users/signup'); diff --git a/server/test/index.test.js b/server/test/index.test.js index 56106ec..d3055e6 100644 --- a/server/test/index.test.js +++ b/server/test/index.test.js @@ -41,6 +41,30 @@ describe('Tests login route', () => { }); }); +describe('Tests login route to admin', () => { + test(' login route /login ', async () => { + const res = await supertest(app) + .post('/api/v1/adminLogin') + .send({ + email: 'mohmsal96@gmail.com', + password: '123456', + }) + .expect(200); + return expect(res.body).toEqual({ message: 'You are Logged Successfully' }); + }); + + test(' login route /login with error in email or password ', async () => { + const res = await supertest(app) + .post('/api/v1/adminLogin') + .send({ + email: 'msal96@gmail.com', + password: '1234566', + }) + .expect(400); + return expect(res.body).toEqual({ message: 'Invalid email or password' }); + }); +}); + describe('user estates', () => { test('get users estates', async () => { const res = await supertest(app) From b648dc517a324a6697cb748bb859992a670f8dbe Mon Sep 17 00:00:00 2001 From: mohammedsalah7 Date: Sun, 31 Oct 2021 17:03:05 +0200 Subject: [PATCH 08/36] create testing end point login admin #69 --- server/test/index.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/test/index.test.js b/server/test/index.test.js index d3055e6..0ce7c8c 100644 --- a/server/test/index.test.js +++ b/server/test/index.test.js @@ -47,7 +47,7 @@ describe('Tests login route to admin', () => { .post('/api/v1/adminLogin') .send({ email: 'mohmsal96@gmail.com', - password: '123456', + password: '1234567894455', }) .expect(200); return expect(res.body).toEqual({ message: 'You are Logged Successfully' }); From 3c4ec92ed9a0f209c6cb2c0574876e1a378eb499 Mon Sep 17 00:00:00 2001 From: ElhamFadel Date: Sun, 31 Oct 2021 18:12:36 +0300 Subject: [PATCH 09/36] edit agint #10 --- server/database/config/connection.js | 2 +- server/routes/estate.js | 6 ++-- server/test/index.test.js | 47 ++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/server/database/config/connection.js b/server/database/config/connection.js index f1ed1f7..4a402a1 100644 --- a/server/database/config/connection.js +++ b/server/database/config/connection.js @@ -23,6 +23,6 @@ switch (NODE_ENV) { const options = { connectionString: dbUrl, - ssl: false, + ssl: { rejectUnauthorized: false }, }; module.exports = new Pool(options); diff --git a/server/routes/estate.js b/server/routes/estate.js index da4cc19..d618318 100644 --- a/server/routes/estate.js +++ b/server/routes/estate.js @@ -1,10 +1,8 @@ const router = require('express').Router(); - -// router.delete('/:estateId', isAuth, isAdmin, deleteEstate); -// const { isAuth, isAdmin } = require('../middleware'); +const { isAuth, isAdmin } = require('../middleware'); const { editEstate, deleteEstate } = require('../controllers'); router.put('/:estateId', editEstate); - +router.delete('/:estateId', isAuth, isAdmin, deleteEstate); router.delete('/:estateId', deleteEstate); module.exports = router; diff --git a/server/test/index.test.js b/server/test/index.test.js index 56106ec..c4e56bc 100644 --- a/server/test/index.test.js +++ b/server/test/index.test.js @@ -181,6 +181,7 @@ describe('Delete Specific Estate By Using Id', () => { }); }); }); + describe('test signup endpoint with all cases ', () => { test('test sign up endpoint when success', async () => { const res = await supertest(app) @@ -250,3 +251,49 @@ describe('test signup endpoint with all cases ', () => { }); }); }); + +describe('test Edit Agent data /users/:iduser ', () => { + test('test 200', async () => { + const res = await supertest(app) + .put('/api/v1/users/1') + .send({ + username: 'test', + email: 'kallport0@patch.com', + phone: '059985555555', + }) + .expect(200) + .expect('Content-Type', /json/); + return expect(res.body).toEqual({ + message: 'Agent\'s data updated successfully', + }); + }); + + test('test 400', async () => { + const res = await supertest(app) + .put('/api/v1/users/1') + .send({ + username: 'test', + email: 'kallport0@patch.com', + phone: '0599', + }) + .expect(400) + .expect('Content-Type', /json/); + return expect(res.body).toEqual({ + message: '"phone" length must be at least 9 characters long', + }); + }); + test('test 404', async () => { + const res = await supertest(app) + .put('/api/v1/users/400') + .send({ + username: 'test', + email: 'kallport0@patch.com', + phone: '059915587555', + }) + .expect(404) + .expect('Content-Type', /json/); + return expect(res.body).toEqual({ + message: 'There\'s no Agent, put correct id', + }); + }); +}); From ab48d036a1f8a8e385a7a95d57103de7130a605e Mon Sep 17 00:00:00 2001 From: ElhamFadel Date: Sun, 31 Oct 2021 19:02:30 +0300 Subject: [PATCH 10/36] remove route delete --- server/routes/estate.js | 1 - 1 file changed, 1 deletion(-) diff --git a/server/routes/estate.js b/server/routes/estate.js index d618318..65cc6b2 100644 --- a/server/routes/estate.js +++ b/server/routes/estate.js @@ -4,5 +4,4 @@ const { editEstate, deleteEstate } = require('../controllers'); router.put('/:estateId', editEstate); router.delete('/:estateId', isAuth, isAdmin, deleteEstate); -router.delete('/:estateId', deleteEstate); module.exports = router; From 166b037eadd8ed8607b0787fb81491befcb08d4f Mon Sep 17 00:00:00 2001 From: ElhamFadel Date: Sun, 31 Oct 2021 19:32:09 +0300 Subject: [PATCH 11/36] edit --- server/controllers/users/putAgent.js | 2 +- server/routes/index.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/server/controllers/users/putAgent.js b/server/controllers/users/putAgent.js index a405276..519e96e 100644 --- a/server/controllers/users/putAgent.js +++ b/server/controllers/users/putAgent.js @@ -4,7 +4,7 @@ const editAgentSchema = require('../../utils/validation/editAgentSchema'); module.exports = async (req, res, next) => { try { const { userId } = req.params; - const { error, value } = await editAgentSchema.validate({ ...req.body, userId }); + const { error, value } = editAgentSchema.validate({ ...req.body, userId }); if (error) return res.status(400).json({ message: error.details[0].message }); const { rowCount } = await putAgent(value); if (rowCount === 1) { diff --git a/server/routes/index.js b/server/routes/index.js index cf86ebe..b844c96 100644 --- a/server/routes/index.js +++ b/server/routes/index.js @@ -3,7 +3,6 @@ const auth = require('./auth'); const estate = require('./estate'); const users = require('./users'); -router.use('/users', users); router.use('/estate', estate); router.use('/users', users); router.use('/', auth); From 069f94d85dbf85e5f8b6f2727019fd9a5e700e60 Mon Sep 17 00:00:00 2001 From: muhammadharoun Date: Mon, 1 Nov 2021 10:40:54 +0200 Subject: [PATCH 12/36] complete sign up admin --- server/controllers/admins/index.js | 3 +++ server/controllers/admins/signupAdmin.js | 2 +- server/database/quieres/index.js | 2 ++ server/database/quieres/signUpAdminQuery.js | 3 +++ server/routes/admin.js | 6 ++++++ server/routes/index.js | 2 ++ server/test/index.test.js | 18 ++++++++++++++++++ 7 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 server/database/quieres/signUpAdminQuery.js create mode 100644 server/routes/admin.js diff --git a/server/controllers/admins/index.js b/server/controllers/admins/index.js index e69de29..c343a2d 100644 --- a/server/controllers/admins/index.js +++ b/server/controllers/admins/index.js @@ -0,0 +1,3 @@ +const signupAdmin = require('./signupAdmin'); + +module.exports = { signupAdmin }; diff --git a/server/controllers/admins/signupAdmin.js b/server/controllers/admins/signupAdmin.js index 23f864a..a143468 100644 --- a/server/controllers/admins/signupAdmin.js +++ b/server/controllers/admins/signupAdmin.js @@ -1,6 +1,6 @@ const { hash } = require('bcrypt'); const adminSchema = require('../../utils/validation/adminSchema'); -const signUpAdminQuery = require('../../database/quieres'); +const { signUpAdminQuery } = require('../../database/quieres'); const { signToken } = require('../../utils'); module.exports = async (req, res, next) => { diff --git a/server/database/quieres/index.js b/server/database/quieres/index.js index 9c42a66..ed76f57 100644 --- a/server/database/quieres/index.js +++ b/server/database/quieres/index.js @@ -4,6 +4,7 @@ const checkAdminQuery = require('./checkAdmin'); const checkEmailQuery = require('./checkEmailQuery'); const editEstateQuery = require('./editEstatesQuery'); const deleteEstateQuery = require('./deleteEstateQuery'); +const signUpAdminQuery = require('./signUpAdminQuery'); module.exports = { getAllUsersQuery, @@ -12,4 +13,5 @@ module.exports = { checkEmailQuery, editEstateQuery, deleteEstateQuery, + signUpAdminQuery, }; diff --git a/server/database/quieres/signUpAdminQuery.js b/server/database/quieres/signUpAdminQuery.js new file mode 100644 index 0000000..2507b9e --- /dev/null +++ b/server/database/quieres/signUpAdminQuery.js @@ -0,0 +1,3 @@ +const connection = require('../config/connection'); + +module.exports = (userName, password, email) => connection.query('INSERT INTO admins (username,password, email) VALUES ($1,$2,$3)', [userName, password, email]); diff --git a/server/routes/admin.js b/server/routes/admin.js new file mode 100644 index 0000000..3a03bde --- /dev/null +++ b/server/routes/admin.js @@ -0,0 +1,6 @@ +const router = require('express').Router(); +const { signupAdmin } = require('../controllers/admins'); + +router.post('/signupadmin', signupAdmin); + +module.exports = router; diff --git a/server/routes/index.js b/server/routes/index.js index eb1e629..068e055 100644 --- a/server/routes/index.js +++ b/server/routes/index.js @@ -2,8 +2,10 @@ const router = require('express').Router(); const auth = require('./auth'); const estate = require('./estate'); const users = require('./users'); +const admins = require('./admin'); router.use('/users', users); +router.use('/admin', admins); router.use('/estate', estate); router.use('/', auth); diff --git a/server/test/index.test.js b/server/test/index.test.js index 56106ec..6e215b5 100644 --- a/server/test/index.test.js +++ b/server/test/index.test.js @@ -250,3 +250,21 @@ describe('test signup endpoint with all cases ', () => { }); }); }); + +describe('test signup as admin ', () => { + test('test sign up endpoint when success', async () => { + const res = await supertest(app) + .post('/api/v1/admin/signupadmin') + .send({ + username: 'test', + password: 'test123456', + email: 'test@gmail.com', + }) + .expect(201) + .expect((response) => expect(response.header['set-cookie'][0].split('=')[0]).toBe('token')) + .expect('Content-Type', /json/); + return expect(res.body).toEqual({ + message: 'user created', + }); + }); +}); From c8cf50a7c194243b2d82b4de9d63aaf4e7656fbf Mon Sep 17 00:00:00 2001 From: ElhamFadel Date: Mon, 1 Nov 2021 13:56:23 +0300 Subject: [PATCH 13/36] search bar --- client/package.json | 56 -------------------------- client/src/App.js | 8 +++- client/src/components/Search/index.js | 11 +++++ client/src/components/Search/style.css | 0 client/src/components/index.js | 1 + 5 files changed, 18 insertions(+), 58 deletions(-) delete mode 100644 client/package.json create mode 100644 client/src/components/Search/index.js create mode 100644 client/src/components/Search/style.css diff --git a/client/package.json b/client/package.json deleted file mode 100644 index b900884..0000000 --- a/client/package.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "client", - "version": "0.1.0", - "private": true, - "proxy": "http://localhost:5000", - "dependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@mui/material": "^5.0.4", - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^11.2.7", - "@testing-library/user-event": "^12.8.3", - "axios": "^0.23.0", - "eslint-config-react-app": "^6.0.0", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "react-router-dom": "^5.3.0", - "react-scripts": "4.0.3", - "web-vitals": "^1.1.2" - }, - "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" - }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - }, - "devDependencies": { - "eslint": "^7.32.0", - "eslint-config-airbnb": "^18.2.1", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-jsx-a11y": "^6.4.1", - "eslint-plugin-prettier": "^4.0.0", - "eslint-plugin-react": "^7.26.1", - "eslint-plugin-react-hooks": "^4.2.0", - "prettier": "^2.4.1" - } -} diff --git a/client/src/App.js b/client/src/App.js index 2a4bc88..677c016 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,7 +1,11 @@ +import {Search} from "./components" function App() { return ( -
- +
+ + +
+ ); } diff --git a/client/src/components/Search/index.js b/client/src/components/Search/index.js new file mode 100644 index 0000000..f6dc12d --- /dev/null +++ b/client/src/components/Search/index.js @@ -0,0 +1,11 @@ +import React from 'react' +import "./style.css" +function Search() { + return ( +
+ Hello +
+ ) +} + +export default Search diff --git a/client/src/components/Search/style.css b/client/src/components/Search/style.css new file mode 100644 index 0000000..e69de29 diff --git a/client/src/components/index.js b/client/src/components/index.js index e69de29..5f65bc8 100644 --- a/client/src/components/index.js +++ b/client/src/components/index.js @@ -0,0 +1 @@ +export { default as Search } from './Search'; \ No newline at end of file From ee5edea3b82f26a3d10660ce06f347502fe86ae0 Mon Sep 17 00:00:00 2001 From: Muhammad Abdulhadi Date: Mon, 1 Nov 2021 15:46:47 +0200 Subject: [PATCH 14/36] Fix logout response and edit admin signup route --- server/controllers/logout.js | 2 +- server/routes/admin.js | 2 +- server/test/index.test.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/controllers/logout.js b/server/controllers/logout.js index d04e524..7498b19 100644 --- a/server/controllers/logout.js +++ b/server/controllers/logout.js @@ -1,4 +1,4 @@ const logout = (req, res) => { - res.clearCookie('token'); + res.clearCookie('token').json({ message: 'Logout Successfully' }); }; module.exports = logout; diff --git a/server/routes/admin.js b/server/routes/admin.js index 3a03bde..5946596 100644 --- a/server/routes/admin.js +++ b/server/routes/admin.js @@ -1,6 +1,6 @@ const router = require('express').Router(); const { signupAdmin } = require('../controllers/admins'); -router.post('/signupadmin', signupAdmin); +router.post('/signup', signupAdmin); module.exports = router; diff --git a/server/test/index.test.js b/server/test/index.test.js index 6e215b5..4215ea7 100644 --- a/server/test/index.test.js +++ b/server/test/index.test.js @@ -254,7 +254,7 @@ describe('test signup endpoint with all cases ', () => { describe('test signup as admin ', () => { test('test sign up endpoint when success', async () => { const res = await supertest(app) - .post('/api/v1/admin/signupadmin') + .post('/api/v1/admin/signup') .send({ username: 'test', password: 'test123456', From cfe9b0021006b9df9f3b1cd960a2450775ee0f85 Mon Sep 17 00:00:00 2001 From: muhammadharoun Date: Mon, 1 Nov 2021 16:45:01 +0200 Subject: [PATCH 15/36] footer --- client/package.json | 2 + client/src/App.js | 6 ++- client/src/assets/facebook.png | Bin 0 -> 575 bytes client/src/assets/homeIcon.png | Bin 0 -> 9099 bytes client/src/components/Footer/Footer.js | 54 ++++++++++++++++++++++++ client/src/components/Footer/footer.css | 23 ++++++++++ client/src/index.js | 3 +- 7 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 client/src/assets/facebook.png create mode 100644 client/src/assets/homeIcon.png create mode 100644 client/src/components/Footer/Footer.js create mode 100644 client/src/components/Footer/footer.css diff --git a/client/package.json b/client/package.json index b900884..09c5c78 100644 --- a/client/package.json +++ b/client/package.json @@ -7,6 +7,7 @@ "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", "@mui/material": "^5.0.4", + "@mui/styles": "^5.0.2", "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^11.2.7", "@testing-library/user-event": "^12.8.3", @@ -14,6 +15,7 @@ "eslint-config-react-app": "^6.0.0", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-icons": "^4.3.1", "react-router-dom": "^5.3.0", "react-scripts": "4.0.3", "web-vitals": "^1.1.2" diff --git a/client/src/App.js b/client/src/App.js index 2a4bc88..b2ac0cc 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,6 +1,10 @@ +import Footer from './components/Footer/Footer'; + function App() { return ( -
+
+
+
); } diff --git a/client/src/assets/facebook.png b/client/src/assets/facebook.png new file mode 100644 index 0000000000000000000000000000000000000000..2a772da13440e75583ab171d9f3d6850b8c7598d GIT binary patch literal 575 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 literal 0 HcmV?d00001 diff --git a/client/src/components/Footer/Footer.js b/client/src/components/Footer/Footer.js new file mode 100644 index 0000000..d1960c6 --- /dev/null +++ b/client/src/components/Footer/Footer.js @@ -0,0 +1,54 @@ +import { + AppBar, Container, Link, +} from '@mui/material'; +import { + AiFillFacebook, AiFillTwitterCircle, AiFillInstagram, AiOutlineWhatsApp, +} from 'react-icons/ai'; +import HomeIcon from '../../assets/homeIcon.png'; + +import './footer.css'; + +export default function Footer() { + return ( + + + +
+ home icon + +
+
+
+ + home + about + privcy + contact us + +
+
+ + + + + + +
+
+
All right reserved @ to this website
+
+ +
+
+
+ + ); +} diff --git a/client/src/components/Footer/footer.css b/client/src/components/Footer/footer.css new file mode 100644 index 0000000..b05eb4f --- /dev/null +++ b/client/src/components/Footer/footer.css @@ -0,0 +1,23 @@ +.section2{ + display: flex; + flex-direction: column; + width: 50%; + align-items: center; + justify-content: space-evenly +} + +.pages { + display: flex; + width: 72%; + justify-content: space-around; +} +.social{ + display: flex; + justify-content: space-evenly; + width: 36%; +} + + +.copyright{ +text-align: center; +} \ No newline at end of file diff --git a/client/src/index.js b/client/src/index.js index 62adcf3..f452ad2 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -7,6 +7,5 @@ ReactDOM.render( , - document.getElementById('root') + document.getElementById('root'), ); - From db4fd5504ead4340bd2bd4dda92ad61f53403038 Mon Sep 17 00:00:00 2001 From: muhammadharoun Date: Mon, 1 Nov 2021 21:33:24 +0200 Subject: [PATCH 16/36] edit footer --- client/src/components/Footer/Footer.js | 80 ++++++++++++++++++++----- client/src/components/Footer/footer.css | 42 +++++++++---- 2 files changed, 96 insertions(+), 26 deletions(-) diff --git a/client/src/components/Footer/Footer.js b/client/src/components/Footer/Footer.js index d1960c6..a115a45 100644 --- a/client/src/components/Footer/Footer.js +++ b/client/src/components/Footer/Footer.js @@ -11,43 +11,93 @@ import './footer.css'; export default function Footer() { return ( - +
home icon
-
+
+

+ About Us +

+ Story + Clients + Testimonials - home - about - privcy - contact us +
+
+

+ Services +

+ Marketing + Consulting + Development + Design
-
- - - - +
+

+ Contact Us +

+ United States + United Kingdom + Australia + Support
-
-
All right reserved @ to this website
+ +
+

+ Social +

+ + + Facebook + + + + Twitter + + + + Instagram + + + + WhatsApp + +
+
+
All right reserved @ to this website
+
); diff --git a/client/src/components/Footer/footer.css b/client/src/components/Footer/footer.css index b05eb4f..1b22df8 100644 --- a/client/src/components/Footer/footer.css +++ b/client/src/components/Footer/footer.css @@ -1,23 +1,43 @@ .section2{ display: flex; - flex-direction: column; width: 50%; + height: 100%; + align-content: center; + justify-content: space-around; align-items: center; - justify-content: space-evenly } + + + -.pages { +.about-us,.services,.contact-us,.social{ display: flex; - width: 72%; - justify-content: space-around; + flex-direction: column; + height: 50%; + } -.social{ - display: flex; - justify-content: space-evenly; - width: 36%; + +.about-us > a,.services > a,.contact-us > a,.social > a{ + font-size: 24px; + margin-bottom: 20px; + font-size: 18px; + text-align: left; + +} +.about-us > a > svg,.services > a > svg,.contact-us > a > svg,.social > a > svg{ + margin-right: 5px; } +.about-us > p,.services > p,.contact-us > p,.social > p{ + font-size: 26px; + color: #fff; + margin-bottom: 40px; + font-weight: bold; + text-align: left; +} -.copyright{ -text-align: center; +.social *{ + display: flex; + align-items: center; + margin-left: 10px; } \ No newline at end of file From d2c126405a2c39c90ba78f39d6c66d424a6f1557 Mon Sep 17 00:00:00 2001 From: ElhamFadel Date: Tue, 2 Nov 2021 12:24:47 +0300 Subject: [PATCH 17/36] change request #10 --- server/routes/auth.js | 7 ------- server/routes/index.js | 7 ++++--- server/routes/users.js | 5 +++-- server/test/index.test.js | 22 +++++++++++----------- 4 files changed, 18 insertions(+), 23 deletions(-) delete mode 100644 server/routes/auth.js diff --git a/server/routes/auth.js b/server/routes/auth.js deleted file mode 100644 index ad9201b..0000000 --- a/server/routes/auth.js +++ /dev/null @@ -1,7 +0,0 @@ -const router = require('express').Router(); -const { logout, login } = require('../controllers'); - -router.get('/logout', logout); -router.post('/login', login); - -module.exports = router; diff --git a/server/routes/index.js b/server/routes/index.js index b844c96..d583f2e 100644 --- a/server/routes/index.js +++ b/server/routes/index.js @@ -1,10 +1,11 @@ const router = require('express').Router(); -const auth = require('./auth'); const estate = require('./estate'); const users = require('./users'); +const { logout, login } = require('../controllers'); +router.get('/logout', logout); +router.post('/login', login); router.use('/estate', estate); -router.use('/users', users); -router.use('/', auth); +router.use('/user', users); module.exports = router; diff --git a/server/routes/users.js b/server/routes/users.js index 0b886a4..f0fb69e 100644 --- a/server/routes/users.js +++ b/server/routes/users.js @@ -1,14 +1,15 @@ const router = require('express').Router(); const { - userEstateshandler, getAllUsers, logout, putAgent, + userEstateshandler, getAllUsers, putAgent, } = require('../controllers'); const estate = require('./estate'); const signup = require('../controllers/users/signup'); +const { isAuth } = require('../middleware'); router.use('/estate', estate); router.post('/signup', signup); router.get('/:userId/estates', userEstateshandler); -router.put('/:userId', putAgent); +router.put('/:userId', isAuth, putAgent); router.get('/', getAllUsers); module.exports = router; diff --git a/server/test/index.test.js b/server/test/index.test.js index c4e56bc..574f241 100644 --- a/server/test/index.test.js +++ b/server/test/index.test.js @@ -10,7 +10,7 @@ afterAll(() => connection.end()); describe('Get all users', () => { test('get all users', async () => { const res = await supertest(app) - .get('/api/v1/users') + .get('/api/v1/user') .expect(200) .expect('Content-Type', /json/); return expect(3).toEqual(res.body.data.length); @@ -44,7 +44,7 @@ describe('Tests login route', () => { describe('user estates', () => { test('get users estates', async () => { const res = await supertest(app) - .get('/api/v1/users/3/estates') + .get('/api/v1/user/3/estates') .expect(200) .expect('Content-Type', /json/); return expect(res.body).toEqual({ @@ -96,7 +96,7 @@ describe('user estates', () => { describe('user estates', () => { test('get users estates', async () => { const res = await supertest(app) - .get('/api/v1/users/three/estates') + .get('/api/v1/user/three/estates') .expect(404) .expect('Content-Type', /json/); return expect(res.body).toEqual({ @@ -185,7 +185,7 @@ describe('Delete Specific Estate By Using Id', () => { describe('test signup endpoint with all cases ', () => { test('test sign up endpoint when success', async () => { const res = await supertest(app) - .post('/api/v1/users/signup') + .post('/api/v1/user/signup') .send({ username: 'test', password: 'test123456', @@ -203,7 +203,7 @@ describe('test signup endpoint with all cases ', () => { test('test signup error validation phone" length must be 10 characters long ', async () => { const res = await supertest(app) - .post('/api/v1/users/signup') + .post('/api/v1/user/signup') .send({ username: 'Kai', password: '1234567894455', @@ -219,7 +219,7 @@ describe('test signup endpoint with all cases ', () => { }); test('test signup username or phone already exists ', async () => { const res = await supertest(app) - .post('/api/v1/users/signup') + .post('/api/v1/user/signup') .send({ username: 'Kai', password: '1234567894455', @@ -236,7 +236,7 @@ describe('test signup endpoint with all cases ', () => { test('test signup confirmpassword ', async () => { const res = await supertest(app) - .post('/api/v1/users/signup') + .post('/api/v1/user/signup') .send({ username: 'test', password: 'test123456', @@ -252,10 +252,10 @@ describe('test signup endpoint with all cases ', () => { }); }); -describe('test Edit Agent data /users/:iduser ', () => { +describe('test Edit Agent data /user/:iduser ', () => { test('test 200', async () => { const res = await supertest(app) - .put('/api/v1/users/1') + .put('/api/v1/user/1') .send({ username: 'test', email: 'kallport0@patch.com', @@ -270,7 +270,7 @@ describe('test Edit Agent data /users/:iduser ', () => { test('test 400', async () => { const res = await supertest(app) - .put('/api/v1/users/1') + .put('/api/v1/user/1') .send({ username: 'test', email: 'kallport0@patch.com', @@ -284,7 +284,7 @@ describe('test Edit Agent data /users/:iduser ', () => { }); test('test 404', async () => { const res = await supertest(app) - .put('/api/v1/users/400') + .put('/api/v1/user/400') .send({ username: 'test', email: 'kallport0@patch.com', From 3e7fbfc08bc3d2e23f5007d8ce9844a2cfd80adc Mon Sep 17 00:00:00 2001 From: muhammadharoun Date: Tue, 2 Nov 2021 14:15:37 +0200 Subject: [PATCH 18/36] create user info card --- client/package.json | 2 + client/src/App.js | 8 +- client/src/assets/profile-picture.jpg | Bin 0 -> 53775 bytes .../UserContacatCard/UserContactCard.js | 71 ++++++++++++++++++ .../UserContacatCard/userContactCard.css | 0 client/src/index.js | 3 +- 6 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 client/src/assets/profile-picture.jpg create mode 100644 client/src/components/UserContacatCard/UserContactCard.js create mode 100644 client/src/components/UserContacatCard/userContactCard.css diff --git a/client/package.json b/client/package.json index b900884..de043a7 100644 --- a/client/package.json +++ b/client/package.json @@ -6,7 +6,9 @@ "dependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", + "@mui/icons-material": "^5.0.5", "@mui/material": "^5.0.4", + "@mui/styles": "^5.0.2", "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^11.2.7", "@testing-library/user-event": "^12.8.3", diff --git a/client/src/App.js b/client/src/App.js index 2a4bc88..6081599 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,8 +1,12 @@ +import UserContactCard from './components/UserContacatCard/UserContactCard'; +import HomeIcon from './assets/profile-picture.jpg'; + function App() { return ( -
+
+ +
); } - export default App; diff --git a/client/src/assets/profile-picture.jpg b/client/src/assets/profile-picture.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fdc5ea59390f8d48a426b93a276d69ab0d7f60e3 GIT binary patch literal 53775 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 + + + + + Mohammed haroon + + + Building Owner + + + Contact Info: + + + + + gaza , palestine + + + + + +970595222222 + + + + + info@gmail.com + + + + + ); +} + +export default userContactCard; diff --git a/client/src/components/UserContacatCard/userContactCard.css b/client/src/components/UserContacatCard/userContactCard.css new file mode 100644 index 0000000..e69de29 diff --git a/client/src/index.js b/client/src/index.js index 62adcf3..f452ad2 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -7,6 +7,5 @@ ReactDOM.render( , - document.getElementById('root') + document.getElementById('root'), ); - From d67fb18a0da31010a665fa21853bacb7a8998f8a Mon Sep 17 00:00:00 2001 From: muhammadharoun Date: Tue, 2 Nov 2021 14:28:03 +0200 Subject: [PATCH 19/36] make data as props --- client/src/App.js | 7 +------ .../components/UserContacatCard/UserContactCard.js | 12 +++++++----- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/client/src/App.js b/client/src/App.js index 6081599..60f3c52 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,11 +1,6 @@ -import UserContactCard from './components/UserContacatCard/UserContactCard'; -import HomeIcon from './assets/profile-picture.jpg'; - function App() { return ( -
- -
+
); } diff --git a/client/src/components/UserContacatCard/UserContactCard.js b/client/src/components/UserContacatCard/UserContactCard.js index 1c84ee4..8a29878 100644 --- a/client/src/components/UserContacatCard/UserContactCard.js +++ b/client/src/components/UserContacatCard/UserContactCard.js @@ -26,7 +26,9 @@ const useStyles = makeStyles({ }, }); const contentStyles = { display: 'flex', marginBottom: '15px', alignItems: 'center' }; -function userContactCard({ image }) { +function userContactCard({ + image, name, location, phone, email, +}) { const classes = useStyles(); return ( @@ -39,7 +41,7 @@ function userContactCard({ image }) { /> - Mohammed haroon + {name} Building Owner @@ -50,17 +52,17 @@ function userContactCard({ image }) { - gaza , palestine + {location} - +970595222222 + {phone} - info@gmail.com + {email} From c11750723245e45d357f57885000912b34329678 Mon Sep 17 00:00:00 2001 From: Elham Fadel <65178119+ElhamFadel@users.noreply.github.com> Date: Tue, 2 Nov 2021 17:10:07 +0300 Subject: [PATCH 20/36] Update index.js --- server/routes/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/routes/index.js b/server/routes/index.js index f51e6c8..7561779 100644 --- a/server/routes/index.js +++ b/server/routes/index.js @@ -2,10 +2,9 @@ const router = require('express').Router(); const estate = require('./estate'); const users = require('./users'); const admins = require('./admin'); -const { logout, login } = require('../controllers'); +const { logout } = require('../controllers'); router.get('/logout', logout); -router.post('/login', login); router.use('/admin', admins); router.use('/estate', estate); router.use('/user', users); From d868c906bbcf7f342d84bd2a7f2843804ab5f07f Mon Sep 17 00:00:00 2001 From: Elham Fadel <65178119+ElhamFadel@users.noreply.github.com> Date: Tue, 2 Nov 2021 17:12:02 +0300 Subject: [PATCH 21/36] Update users.js add login route --- server/routes/users.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/routes/users.js b/server/routes/users.js index f0fb69e..d33b845 100644 --- a/server/routes/users.js +++ b/server/routes/users.js @@ -1,6 +1,6 @@ const router = require('express').Router(); const { - userEstateshandler, getAllUsers, putAgent, + userEstateshandler, getAllUsers, putAgent,login } = require('../controllers'); const estate = require('./estate'); const signup = require('../controllers/users/signup'); @@ -8,6 +8,7 @@ const { isAuth } = require('../middleware'); router.use('/estate', estate); router.post('/signup', signup); +router.post('/login', login); router.get('/:userId/estates', userEstateshandler); router.put('/:userId', isAuth, putAgent); router.get('/', getAllUsers); From 3fabdd64dfa4299e18960f28cebbf0c7767c3689 Mon Sep 17 00:00:00 2001 From: muhammadharoun Date: Tue, 2 Nov 2021 16:42:12 +0200 Subject: [PATCH 22/36] create home images --- .../components/ImageSection/ImageSection.js | 28 +++++++++++++++++++ .../components/ImageSection/imageSection.css | 25 +++++++++++++++++ client/src/index.js | 3 +- 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 client/src/components/ImageSection/ImageSection.js create mode 100644 client/src/components/ImageSection/imageSection.css diff --git a/client/src/components/ImageSection/ImageSection.js b/client/src/components/ImageSection/ImageSection.js new file mode 100644 index 0000000..933d6a8 --- /dev/null +++ b/client/src/components/ImageSection/ImageSection.js @@ -0,0 +1,28 @@ +import './imageSection.css'; + +function imageSection({ arr }) { + const mainImage = arr[0]; + const images = arr.slice(1); + return ( +
+
+ home +
+
+ {images.map((item) => ( + home + ))} +
+
+ ); +} + +export default imageSection; diff --git a/client/src/components/ImageSection/imageSection.css b/client/src/components/ImageSection/imageSection.css new file mode 100644 index 0000000..68c6dbf --- /dev/null +++ b/client/src/components/ImageSection/imageSection.css @@ -0,0 +1,25 @@ +.main{ + display: flex; + width: 80%; + height: 60vh; +} +.bigImage{ + width: 70%; +} +.bigImage img{ + min-width: 100%; + max-height: 100% +} +.anotherImage{ + display: flex; + flex-direction:column; + width: 30%; + justify-content: space-between + +} +.anotherImage img{ + min-width: 100%; + min-height: 30%; + margin-left:10px; + /* margin-top: 10px; */ +} \ No newline at end of file diff --git a/client/src/index.js b/client/src/index.js index 62adcf3..f452ad2 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -7,6 +7,5 @@ ReactDOM.render( , - document.getElementById('root') + document.getElementById('root'), ); - From 281641ef84dc03a69c7d460eec64082abfe4e14a Mon Sep 17 00:00:00 2001 From: muhammadharoun Date: Tue, 2 Nov 2021 16:46:50 +0200 Subject: [PATCH 23/36] use prettier to css code --- client/src/components/Footer/footer.css | 75 ++++++++++++++----------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/client/src/components/Footer/footer.css b/client/src/components/Footer/footer.css index 1b22df8..9465b74 100644 --- a/client/src/components/Footer/footer.css +++ b/client/src/components/Footer/footer.css @@ -1,43 +1,50 @@ -.section2{ - display: flex; - width: 50%; - height: 100%; - align-content: center; - justify-content: space-around; - align-items: center; +.section2 { + display: flex; + width: 50%; + height: 100%; + align-content: center; + justify-content: space-around; + align-items: center; } - - - - -.about-us,.services,.contact-us,.social{ - display: flex; - flex-direction: column; - height: 50%; +.about-us, +.services, +.contact-us, +.social { + display: flex; + flex-direction: column; + height: 50%; } -.about-us > a,.services > a,.contact-us > a,.social > a{ - font-size: 24px; - margin-bottom: 20px; - font-size: 18px; - text-align: left; - +.about-us > a, +.services > a, +.contact-us > a, +.social > a { + font-size: 24px; + margin-bottom: 20px; + font-size: 18px; + text-align: left; } -.about-us > a > svg,.services > a > svg,.contact-us > a > svg,.social > a > svg{ - margin-right: 5px; +.about-us > a > svg, +.services > a > svg, +.contact-us > a > svg, +.social > a > svg { + margin-right: 5px; } -.about-us > p,.services > p,.contact-us > p,.social > p{ - font-size: 26px; - color: #fff; - margin-bottom: 40px; - font-weight: bold; - text-align: left; +.about-us > p, +.services > p, +.contact-us > p, +.social > p { + font-size: 26px; + color: #fff; + margin-bottom: 40px; + font-weight: bold; + text-align: left; } -.social *{ - display: flex; - align-items: center; - margin-left: 10px; -} \ No newline at end of file +.social * { + display: flex; + align-items: center; + margin-left: 10px; +} From 7733346e04f25dda981ebdfa4d1b2be65a890705 Mon Sep 17 00:00:00 2001 From: ElhamFadel Date: Wed, 3 Nov 2021 12:19:45 +0300 Subject: [PATCH 24/36] edit endpoint #10 --- server/controllers/users/login.js | 3 ++- server/controllers/users/putAgent.js | 2 +- server/controllers/users/signup.js | 4 ++-- server/database/config/connection.js | 2 +- server/routes/index.js | 3 +-- server/routes/users.js | 5 +++-- server/utils/tokenFunction.js | 1 + 7 files changed, 11 insertions(+), 9 deletions(-) diff --git a/server/controllers/users/login.js b/server/controllers/users/login.js index 87b99eb..003b937 100644 --- a/server/controllers/users/login.js +++ b/server/controllers/users/login.js @@ -11,16 +11,17 @@ const login = async (req, res, next) => { await loginSchema.validateAsync(req.body); const { rows } = await checkEmailQuery(email); - if (!rows.length) { return res.status(400).json({ message: 'Invalid email or password' }); } const compared = await bcrypt.compare(password, rows[0].password); + if (!compared) { return res.status(400).json({ message: 'Invalid email or password' }); } const token = await signToken(email, rows[0].id); + console.log(token); return res.cookie('token', token).json({ message: 'You are Logged Successfully' }); } catch (err) { if (err.details) { diff --git a/server/controllers/users/putAgent.js b/server/controllers/users/putAgent.js index 519e96e..e47eb2c 100644 --- a/server/controllers/users/putAgent.js +++ b/server/controllers/users/putAgent.js @@ -3,7 +3,7 @@ const editAgentSchema = require('../../utils/validation/editAgentSchema'); module.exports = async (req, res, next) => { try { - const { userId } = req.params; + const { id: userId } = req.user; const { error, value } = editAgentSchema.validate({ ...req.body, userId }); if (error) return res.status(400).json({ message: error.details[0].message }); const { rowCount } = await putAgent(value); diff --git a/server/controllers/users/signup.js b/server/controllers/users/signup.js index ab56711..985af18 100644 --- a/server/controllers/users/signup.js +++ b/server/controllers/users/signup.js @@ -12,8 +12,8 @@ module.exports = async (req, res, next) => { } = agentSchema.validate(req.body); if (error) return res.status(400).json({ message: error.details[0].message }); const hasedPasword = await hash(password, 10); - await signUpQuery(username, email, phone, hasedPasword); - const token = await signToken(email, username, phone); + const { rows } = await signUpQuery(username, email, phone, hasedPasword); + const token = await signToken(email, username, phone, rows[0].id); return res.status(201).cookie('token', token).json({ message: 'user created' }); } catch (err) { if (err.code === '23505') { diff --git a/server/database/config/connection.js b/server/database/config/connection.js index 4a402a1..f1ed1f7 100644 --- a/server/database/config/connection.js +++ b/server/database/config/connection.js @@ -23,6 +23,6 @@ switch (NODE_ENV) { const options = { connectionString: dbUrl, - ssl: { rejectUnauthorized: false }, + ssl: false, }; module.exports = new Pool(options); diff --git a/server/routes/index.js b/server/routes/index.js index d583f2e..ad7a3a6 100644 --- a/server/routes/index.js +++ b/server/routes/index.js @@ -1,10 +1,9 @@ const router = require('express').Router(); const estate = require('./estate'); const users = require('./users'); -const { logout, login } = require('../controllers'); +const { logout } = require('../controllers'); router.get('/logout', logout); -router.post('/login', login); router.use('/estate', estate); router.use('/user', users); diff --git a/server/routes/users.js b/server/routes/users.js index f0fb69e..17cae38 100644 --- a/server/routes/users.js +++ b/server/routes/users.js @@ -1,6 +1,6 @@ const router = require('express').Router(); const { - userEstateshandler, getAllUsers, putAgent, + userEstateshandler, getAllUsers, putAgent, login, } = require('../controllers'); const estate = require('./estate'); const signup = require('../controllers/users/signup'); @@ -9,7 +9,8 @@ const { isAuth } = require('../middleware'); router.use('/estate', estate); router.post('/signup', signup); router.get('/:userId/estates', userEstateshandler); -router.put('/:userId', isAuth, putAgent); +router.put('/', isAuth, putAgent); router.get('/', getAllUsers); +router.post('/login', login); module.exports = router; diff --git a/server/utils/tokenFunction.js b/server/utils/tokenFunction.js index c7ac90e..d6d1b4a 100644 --- a/server/utils/tokenFunction.js +++ b/server/utils/tokenFunction.js @@ -1,4 +1,5 @@ const { verify, sign } = require('jsonwebtoken'); +require('env2')('.env'); const { env: { ACCESS_TOKEN_SECRET }, From d0c1baa9ff0ab0270d38fb8a0d507eb52ce1e32f Mon Sep 17 00:00:00 2001 From: ElhamFadel Date: Wed, 3 Nov 2021 12:27:03 +0300 Subject: [PATCH 25/36] edit endpoint #10 --- server/controllers/users/login.js | 1 - server/database/config/connection.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/server/controllers/users/login.js b/server/controllers/users/login.js index 003b937..e67ba06 100644 --- a/server/controllers/users/login.js +++ b/server/controllers/users/login.js @@ -21,7 +21,6 @@ const login = async (req, res, next) => { return res.status(400).json({ message: 'Invalid email or password' }); } const token = await signToken(email, rows[0].id); - console.log(token); return res.cookie('token', token).json({ message: 'You are Logged Successfully' }); } catch (err) { if (err.details) { diff --git a/server/database/config/connection.js b/server/database/config/connection.js index f1ed1f7..4a402a1 100644 --- a/server/database/config/connection.js +++ b/server/database/config/connection.js @@ -23,6 +23,6 @@ switch (NODE_ENV) { const options = { connectionString: dbUrl, - ssl: false, + ssl: { rejectUnauthorized: false }, }; module.exports = new Pool(options); From 94e8b67fc08969d3ea464ddab674bd2f4f5b6962 Mon Sep 17 00:00:00 2001 From: Muhammad Abdulhadi Date: Wed, 3 Nov 2021 16:22:48 +0200 Subject: [PATCH 26/36] Fixing Tests and multiple controllers --- server/controllers/users/login.js | 2 +- server/controllers/users/putAgent.js | 16 ++++++++------- server/controllers/users/signup.js | 4 +++- server/database/config/fakeData.sql | 2 +- server/database/quieres/account/signUp.js | 2 +- server/routes/estate.js | 4 ++-- server/test/index.test.js | 24 +++++++++++++++++------ 7 files changed, 35 insertions(+), 19 deletions(-) diff --git a/server/controllers/users/login.js b/server/controllers/users/login.js index e67ba06..696baf6 100644 --- a/server/controllers/users/login.js +++ b/server/controllers/users/login.js @@ -20,7 +20,7 @@ const login = async (req, res, next) => { if (!compared) { return res.status(400).json({ message: 'Invalid email or password' }); } - const token = await signToken(email, rows[0].id); + const token = await signToken({ email, userId: rows[0].id }); return res.cookie('token', token).json({ message: 'You are Logged Successfully' }); } catch (err) { if (err.details) { diff --git a/server/controllers/users/putAgent.js b/server/controllers/users/putAgent.js index e47eb2c..c4350f4 100644 --- a/server/controllers/users/putAgent.js +++ b/server/controllers/users/putAgent.js @@ -3,20 +3,22 @@ const editAgentSchema = require('../../utils/validation/editAgentSchema'); module.exports = async (req, res, next) => { try { - const { id: userId } = req.user; + const { userId } = req.user; const { error, value } = editAgentSchema.validate({ ...req.body, userId }); if (error) return res.status(400).json({ message: error.details[0].message }); const { rowCount } = await putAgent(value); if (rowCount === 1) { - res.status(200).json({ + return res.status(200).json({ message: "Agent's data updated successfully", }); - } else { - res.status(404).json({ - message: 'There\'s no Agent, put correct id', - }); } + return res.status(404).json({ + message: 'There\'s no Agent, put correct id', + }); } catch (err) { - next(err); + if (err.detail) { + return res.status(400).json({ message: err.detail }); + } + return next(err); } }; diff --git a/server/controllers/users/signup.js b/server/controllers/users/signup.js index 985af18..1e61264 100644 --- a/server/controllers/users/signup.js +++ b/server/controllers/users/signup.js @@ -13,7 +13,9 @@ module.exports = async (req, res, next) => { if (error) return res.status(400).json({ message: error.details[0].message }); const hasedPasword = await hash(password, 10); const { rows } = await signUpQuery(username, email, phone, hasedPasword); - const token = await signToken(email, username, phone, rows[0].id); + const token = await signToken({ + email, username, phone, userId: rows[0].id, + }); return res.status(201).cookie('token', token).json({ message: 'user created' }); } catch (err) { if (err.code === '23505') { diff --git a/server/database/config/fakeData.sql b/server/database/config/fakeData.sql index 2ad51e6..86061de 100644 --- a/server/database/config/fakeData.sql +++ b/server/database/config/fakeData.sql @@ -1,6 +1,6 @@ -- INSERT INTO agents (name, email, password , phone) - VALUES ('Kai', 'kallport0@patch.com', '$2b$10$gT8Qb2Qe01W1QMRFmH9IC.3bmbA4PS2yG4XQvdkYWxKday.SbjGI2', '677-871-7450'), + VALUES ('Kai', 'kallport0@patch.com', '$2b$10$hZZ2f3zk.pV/9ndMRn78ze47MAh8SN8uy01qeoK8P54tTe526Pqz6', '677-871-7450'), ('Trixie', 'tbeadon1@plala.or.jp', '$2b$10$oNaAu46EHAyOCiufPgchaOQDq5opRxSFHB20m.e3wzDBlM5Yzztf2', '0599832685'), ('Allina', 'aburford2@tumblr.com', '$2b$10$oNaAu46EHAyOCiufPgchaOQDq5opRxSFHB20m.e3wzDBlM5Yzztf2', '630-385-8312'); diff --git a/server/database/quieres/account/signUp.js b/server/database/quieres/account/signUp.js index 80d429c..39bcd98 100644 --- a/server/database/quieres/account/signUp.js +++ b/server/database/quieres/account/signUp.js @@ -1,3 +1,3 @@ const connection = require('../../config/connection'); -module.exports = (userName, email, phone, password) => connection.query('INSERT INTO agents (name,email,phone,password) VALUES ($1,$2,$3,$4)', [userName, email, phone, password]); +module.exports = (userName, email, phone, password) => connection.query('INSERT INTO agents (name,email,phone,password) VALUES ($1,$2,$3,$4) RETURNING id', [userName, email, phone, password]); diff --git a/server/routes/estate.js b/server/routes/estate.js index 65cc6b2..47d4f75 100644 --- a/server/routes/estate.js +++ b/server/routes/estate.js @@ -1,7 +1,7 @@ const router = require('express').Router(); -const { isAuth, isAdmin } = require('../middleware'); +const { isAuth } = require('../middleware'); const { editEstate, deleteEstate } = require('../controllers'); router.put('/:estateId', editEstate); -router.delete('/:estateId', isAuth, isAdmin, deleteEstate); +router.delete('/:estateId', isAuth, deleteEstate); module.exports = router; diff --git a/server/test/index.test.js b/server/test/index.test.js index 488e956..eedad0e 100644 --- a/server/test/index.test.js +++ b/server/test/index.test.js @@ -7,6 +7,8 @@ const connection = require('../database/config/connection'); beforeEach(() => dbBuild()); afterAll(() => connection.end()); +const userToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImthbGxwb3J0MEBwYXRjaC5jb20iLCJ1c2VySWQiOjEsImlhdCI6MTYzNTk0OTE4OX0.LjriIEoRDmj3_52PO8VlsaqekFiItE7gzamngrlaPDk'; + describe('Get all users', () => { test('get all users', async () => { const res = await supertest(app) @@ -20,10 +22,10 @@ describe('Get all users', () => { describe('Tests login route', () => { test(' login route /login ', async () => { const res = await supertest(app) - .post('/api/v1/login') + .post('/api/v1/user/login') .send({ email: 'kallport0@patch.com', - password: '12345', + password: '123456789', }) .expect(200); return expect(res.body).toEqual({ message: 'You are Logged Successfully' }); @@ -31,7 +33,7 @@ describe('Tests login route', () => { test(' login route /login with error in email or password ', async () => { const res = await supertest(app) - .post('/api/v1/login') + .post('/api/v1/user/login') .send({ email: 'kallport0@patch.com', password: '123456987', @@ -180,6 +182,7 @@ describe('Delete Specific Estate By Using Id', () => { test('/estate/:estateId status 200 ', async () => { const res = await supertest(app) .delete('/api/v1/estate/1') + .set('Cookie', [`token=${userToken}`]) .expect(200) .expect('Content-Type', /json/); return expect(res.body).toEqual({ @@ -189,6 +192,7 @@ describe('Delete Specific Estate By Using Id', () => { test('/estate/:estateId status 400, when delete the same estate was deleted or not found ', async () => { const res = await supertest(app) .delete('/api/v1/estate/100') + .set('Cookie', [`token=${userToken}`]) .expect(400) .expect('Content-Type', /json/); return expect(res.body).toEqual({ @@ -198,6 +202,7 @@ describe('Delete Specific Estate By Using Id', () => { test('/estate/:estateId status 400, Invalid estate id ', async () => { const res = await supertest(app) .delete('/api/v1/estate/-121') + .set('Cookie', [`token=${userToken}`]) .expect(400) .expect('Content-Type', /json/); return expect(res.body).toEqual({ @@ -279,7 +284,8 @@ describe('test signup endpoint with all cases ', () => { describe('test Edit Agent data /user/:iduser ', () => { test('test 200', async () => { const res = await supertest(app) - .put('/api/v1/user/1') + .put('/api/v1/user') + .set('Cookie', [`token=${userToken}`]) .send({ username: 'test', email: 'kallport0@patch.com', @@ -294,7 +300,8 @@ describe('test Edit Agent data /user/:iduser ', () => { test('test 400', async () => { const res = await supertest(app) - .put('/api/v1/user/1') + .put('/api/v1/user') + .set('Cookie', [`token=${userToken}`]) .send({ username: 'test', email: 'kallport0@patch.com', @@ -308,7 +315,8 @@ describe('test Edit Agent data /user/:iduser ', () => { }); test('test 404', async () => { const res = await supertest(app) - .put('/api/v1/user/400') + .put('/api/v1/user') + .set('Cookie', ['token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im1hdTdhbW1hZGFiZWRAZ21haWwuY29tIiwidXNlcklkIjo0LCJpYXQiOjE2MzU5NDkyNTl9.St177PIpsDIHAVke6PxoGC8_cJmUrggpyhEcJ4QWKfI']) .send({ username: 'test', email: 'kallport0@patch.com', @@ -318,6 +326,10 @@ describe('test Edit Agent data /user/:iduser ', () => { .expect('Content-Type', /json/); return expect(res.body).toEqual({ message: 'There\'s no Agent, put correct id', + }); + }); +}); + describe('test signup as admin ', () => { test('test sign up endpoint when success', async () => { const res = await supertest(app) From 350caca4306b7ddf39740df18489926c9510cf2a Mon Sep 17 00:00:00 2001 From: muhammadharoun Date: Thu, 4 Nov 2021 12:38:31 +0200 Subject: [PATCH 27/36] change func and file name --- .../UserContacatCard/{UserContactCard.js => index.js} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename client/src/components/UserContacatCard/{UserContactCard.js => index.js} (96%) diff --git a/client/src/components/UserContacatCard/UserContactCard.js b/client/src/components/UserContacatCard/index.js similarity index 96% rename from client/src/components/UserContacatCard/UserContactCard.js rename to client/src/components/UserContacatCard/index.js index 8a29878..72854c2 100644 --- a/client/src/components/UserContacatCard/UserContactCard.js +++ b/client/src/components/UserContacatCard/index.js @@ -26,7 +26,7 @@ const useStyles = makeStyles({ }, }); const contentStyles = { display: 'flex', marginBottom: '15px', alignItems: 'center' }; -function userContactCard({ +function UserContactCard({ image, name, location, phone, email, }) { const classes = useStyles(); @@ -70,4 +70,4 @@ function userContactCard({ ); } -export default userContactCard; +export default UserContactCard; From 3344af241f2091a0fc432eb14612e65ada23e141 Mon Sep 17 00:00:00 2001 From: muhammadharoun Date: Thu, 4 Nov 2021 12:47:35 +0200 Subject: [PATCH 28/36] change func name add margin --- client/src/components/ImageSection/ImageSection.js | 4 ++-- client/src/components/ImageSection/imageSection.css | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/components/ImageSection/ImageSection.js b/client/src/components/ImageSection/ImageSection.js index 933d6a8..774b7a5 100644 --- a/client/src/components/ImageSection/ImageSection.js +++ b/client/src/components/ImageSection/ImageSection.js @@ -1,6 +1,6 @@ import './imageSection.css'; -function imageSection({ arr }) { +function ImageSection({ arr }) { const mainImage = arr[0]; const images = arr.slice(1); return ( @@ -25,4 +25,4 @@ function imageSection({ arr }) { ); } -export default imageSection; +export default ImageSection; diff --git a/client/src/components/ImageSection/imageSection.css b/client/src/components/ImageSection/imageSection.css index 68c6dbf..0a81431 100644 --- a/client/src/components/ImageSection/imageSection.css +++ b/client/src/components/ImageSection/imageSection.css @@ -21,5 +21,6 @@ min-width: 100%; min-height: 30%; margin-left:10px; - /* margin-top: 10px; */ + margin-bottom: 6px; + } \ No newline at end of file From fdff192e6c311a47c9f30283fc52e8e349652ff8 Mon Sep 17 00:00:00 2001 From: ElhamFadel Date: Thu, 4 Nov 2021 21:20:57 +0300 Subject: [PATCH 29/36] changes according request --- package.json | 2 +- server/controllers/users/putAgent.js | 4 +- server/database/config/build.sql | 2 +- server/database/config/connection.js | 2 +- server/database/config/fakeData.sql | 44 +++-- server/test/admins.test.js | 50 ++++++ server/test/{index.test.js => agents.test.js} | 157 ++---------------- server/test/estates.test.js | 90 ++++++++++ 8 files changed, 191 insertions(+), 160 deletions(-) create mode 100644 server/test/admins.test.js rename server/test/{index.test.js => agents.test.js} (58%) create mode 100644 server/test/estates.test.js diff --git a/package.json b/package.json index 84ccd3e..71cba01 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "start": "cross-env NODE_ENV=production node server", "dev": "cross-env NODE_ENV=development nodemon server", - "test": "cross-env NODE_ENV=test jest", + "test": "cross-env NODE_ENV=test jest --runInBand", "build:db": "cross-env NODE_ENV=development node server/database/config" }, "repository": { diff --git a/server/controllers/users/putAgent.js b/server/controllers/users/putAgent.js index c4350f4..1aaa0a7 100644 --- a/server/controllers/users/putAgent.js +++ b/server/controllers/users/putAgent.js @@ -3,7 +3,7 @@ const editAgentSchema = require('../../utils/validation/editAgentSchema'); module.exports = async (req, res, next) => { try { - const { userId } = req.user; + const { id: userId } = req.user; const { error, value } = editAgentSchema.validate({ ...req.body, userId }); if (error) return res.status(400).json({ message: error.details[0].message }); const { rowCount } = await putAgent(value); @@ -12,7 +12,7 @@ module.exports = async (req, res, next) => { message: "Agent's data updated successfully", }); } - return res.status(404).json({ + return res.status(400).json({ message: 'There\'s no Agent, put correct id', }); } catch (err) { diff --git a/server/database/config/build.sql b/server/database/config/build.sql index 3aaa5f2..2f58eb1 100644 --- a/server/database/config/build.sql +++ b/server/database/config/build.sql @@ -31,7 +31,7 @@ CREATE TABLE estates( rooms INTEGER DEFAULT 0, space DECIMAL NOT NULL , approved BOOLEAN DEFAULT FALSE, - rate INTEGER DEFAULT 0, + rate DECIMAL DEFAULT 0, available BOOLEAN DEFAULT TRUE ); diff --git a/server/database/config/connection.js b/server/database/config/connection.js index 4a402a1..f1ed1f7 100644 --- a/server/database/config/connection.js +++ b/server/database/config/connection.js @@ -23,6 +23,6 @@ switch (NODE_ENV) { const options = { connectionString: dbUrl, - ssl: { rejectUnauthorized: false }, + ssl: false, }; module.exports = new Pool(options); diff --git a/server/database/config/fakeData.sql b/server/database/config/fakeData.sql index 86061de..ab48d18 100644 --- a/server/database/config/fakeData.sql +++ b/server/database/config/fakeData.sql @@ -2,24 +2,40 @@ INSERT INTO agents (name, email, password , phone) VALUES ('Kai', 'kallport0@patch.com', '$2b$10$hZZ2f3zk.pV/9ndMRn78ze47MAh8SN8uy01qeoK8P54tTe526Pqz6', '677-871-7450'), ('Trixie', 'tbeadon1@plala.or.jp', '$2b$10$oNaAu46EHAyOCiufPgchaOQDq5opRxSFHB20m.e3wzDBlM5Yzztf2', '0599832685'), -('Allina', 'aburford2@tumblr.com', '$2b$10$oNaAu46EHAyOCiufPgchaOQDq5opRxSFHB20m.e3wzDBlM5Yzztf2', '630-385-8312'); +('Allina', 'aburford2@tumblr.com', '$2b$10$oNaAu46EHAyOCiufPgchaOQDq5opRxSFHB20m.e3wzDBlM5Yzztf2', '630-385-8312'), +('Fadel','fadel@gmail.com','$2b$10$oNaAu46EHAyOCiufPgchaOQDq5opRxSFHB20m.e3wzDBlM5Yzztf2','0597854785'), +('Kelsey','kelsey@gmail.com','$2b$10$oNaAu46EHAyOCiufPgchaOQDq5opRxSFHB20m.e3wzDBlM5Yzztf2','0597854755'); + INSERT INTO admins (username, password , email) VALUES ('ameera', '$2b$10$oNaAu46EHAyOCiufPgchaOQDq5opRxSFHB20m.e3wzDBlM5Yzztf2', 'ameera2021abed@gmail.com'), ('haroon', '$2b$10$oNaAu46EHAyOCiufPgchaOQDq5opRxSFHB20m.e3wzDBlM5Yzztf2', 'hro19502001@gmail.com'), ('elham', '$2b$10$oNaAu46EHAyOCiufPgchaOQDq5opRxSFHB20m.e3wzDBlM5Yzztf2', 'elham2000fadel@gmail.com'), ('sallah', '$2b$10$oNaAu46EHAyOCiufPgchaOQDq5opRxSFHB20m.e3wzDBlM5Yzztf2', 'mohmsal96@gmail.com'); -INSERT INTO estates ( agent_id, title, price, description, type, category, street, city, region, bathrooms, bedrooms, rooms, space, approved, rate, available) VALUES (1, 'suscipit ligula in', 190483.22, 'tristique', 'Buy', 'House', '3152 Morningstar Park', 'Edinburgh of the Seven Seas', 'Saint Helena', 2, 1, 1, 194, false, 2, false), - (2, 'ipsum primis in', 242471.89, 'est quam pharetra magna ac consequat metus sapien ut nunc vestibulum ante', 'Buy', 'House', '100 Butternut Hill', 'Bern', 'Switzerland', 1, 2, 2, 226, true, 5, true), - (3, 'rhoncus sed vestibulum', 84726.00, 'massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in', 'Buy', 'House', '0824 Mcguire Way', 'Kungshamn', 'Sweden', 1, 3, 3, 235, true, 5, false), -(1, 'sociis natoque penatibus et', 106226.71, 'quis odio consequat', 'Buy', 'House', '15918 Mcguire Point', 'Ranong', 'Thailand', 2, 4, 4, 244, true, 1, false), - (2, 'in faucibus orci luctus', 116162.27, 'parturient montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum', 'Buy', 'House', '898 Dixon Crossing', 'Gelap', 'Indonesia', 3, 2, 4, 150, false, 3, false), - (3, 'vestibulum ante ipsum primis', 194193.55, 'leo odio porttitor id consequat in consequat ut nulla sed', 'Buy', 'House', '0891 7th Park', 'Álimos', 'Greece', 1, 3, 2, 174, false, 1, false); +INSERT INTO estates ( agent_id, title, price, description, type, category, street, city, region, bathrooms, bedrooms, rooms, space, approved, rate, available) VALUES + (1, 'Queen bed', 2152, 'A beautiful log house imported directly from Finland to be the perfect retreat from busy city life.', 'sale', 'whole house', 'Omare street', 'Gaza', 'Gaza', 2, 3, 4, 1200, true, 3.5,true), + (1, 'Decorated house', 242.89, 'A unique private house with a high wooden ceiling, wide and lit spaces, a yard house surrounded by plants and fruit trees, seating and grass corners. In addition, the house contains games for children of various ages(box games, table tennis, etc.) The house is located in a carriage on a quiet street and within walking distance to a commercial center that Kemer kept open on Saturday as well as for recreational areas ("artists stables")', 'rent', 'apartment', '100 Butternut Hill', 'Bern', 'Switzerland', 1, 2, 2, 226, true, 5, true), + (3, 'Amazing house in Galilee', 847.00, 'Big beautiful stonehouse with garden and balcony with breathtaking view. A large fireplace and cousy livingroom. A lot of plants and artistic decoration. Harashim lays on top of a mountain in Galilee. Great for relaxing vacation and sightseeing.', 'sale', 'villa', '0824 Mcguire Way', 'Kungshamn', 'Galilee', 1, 3, 3, 235, true, 5, true), +(2, 'Ecologic mud house facing Mt Tabor', 106.71, 'n the pastoral KIBUTZ Beit Keshet you will find our special ecologic mud house. The house is 130 sqm, with a large garden facing Mt Tabor. 5 min walk will take you to the forest, 25 min driving you will be in the sea of galilee.', 'rent', 'villa', '15918 Mcguire Point', 'Ranong', 'Thailand', 2, 4, 4, 244, true, 1, true), + (2, 'in faucibus orci luctus', 116162.27, 'parturient montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum', 'rent', 'villa', '898 Dixon Crossing', 'Gelap', 'Indonesia', 3, 2, 4, 150, false, 3, false), + (3, 'vestibulum ante ipsum primis', 194193.55, 'leo odio porttitor id consequat in consequat ut nulla sed', 'sale', 'whole house', '0891 7th Park', 'Álimos', 'Greece', 1, 3, 2, 174, false, 1, false); + +INSERT INTO images ( estate_id, image) VALUES (1,'https://a0.muscache.com/im/pictures/65ad24f5-3c4f-4340-8e75-1c84278361f1.jpg'), +(1,'https://a0.muscache.com/im/pictures/9ccfb248-370e-49c8-833b-72a649908d5a.jpg'), +(1,'https://a0.muscache.com/im/pictures/039384b0-75de-4c34-aae2-6fd5c76a2b50.jpg'), +(1,'https://a0.muscache.com/im/pictures/c8e4ccb3-b13a-42a0-a1e3-8d48199b81a8.jpg'), + (2,'https://a0.muscache.com/im/pictures/miso/Hosting-37479423/original/9106de21-4abc-4dc6-ae10-8e071dcb4977.jpeg'), + (2,'https://a0.muscache.com/im/pictures/miso/Hosting-37479423/original/3072b6e9-3709-46a7-9bcf-3fee6c96b8bf.jpeg'), + (2,'https://a0.muscache.com/im/pictures/8d432dcd-6023-4d94-804b-f38e76d8e9b8.jpg'), + (2,'https://a0.muscache.com/im/pictures/878fdb40-1ded-4e5b-989f-20097ca59c89.jpg'), + (3,'https://a0.muscache.com/im/pictures/d87542ce-1089-44b7-b3a0-2ef397825fac.jpg'), + (3,'https://a0.muscache.com/im/pictures/2f64652d-7bce-48ef-96ac-61d74b3c70c4.jpg'), + (3,'https://a0.muscache.com/im/pictures/8673fa65-04a7-4a29-acfe-d6806ef01605.jpg'), + (3,'https://a0.muscache.com/im/pictures/5bea56a8-1028-410e-9891-4266b58d6dd4.jpg'), + (2,'https://a0.muscache.com/im/pictures/79715735/f68f24e3_original.jpg'), + (2,'https://a0.muscache.com/im/pictures/79716661/5ae7300a_original.jpg'), + (2,'https://a0.muscache.com/im/pictures/79716124/5a836c95_original.jpg'), + (2,'https://a0.muscache.com/im/pictures/71393509/07948f45_original.jpg'); + + -INSERT INTO images ( estate_id, image) VALUES (1,'https://archello.s3.eu-central-1.amazonaws.com/images/2018/05/17/1.tobiarchitects.1526566679.5654.jpg'), - (2,'https://archello.s3.eu-central-1.amazonaws.com/images/2018/05/17/2.tobiarchitects.1526566679.5654.jpg'), - (3,'https://archello.s3.eu-central-1.amazonaws.com/images/2018/05/17/3.tobiarchitects.1526566679.5654.jpg'), - (1,'https://archello.s3.eu-central-1.amazonaws.com/images/2018/05/17/4.tobiarchitects.1526566679.5654.jpg'), - (2,'https://archello.s3.eu-central-1.amazonaws.com/images/2018/05/17/5.tobiarchitects.1526566679.5654.jpg'), - (3,'https://archello.s3.eu-central-1.amazonaws.com/images/2018/05/17/6.tobiarchitects.1526566679.5654.jpg'); - diff --git a/server/test/admins.test.js b/server/test/admins.test.js new file mode 100644 index 0000000..2cf26a6 --- /dev/null +++ b/server/test/admins.test.js @@ -0,0 +1,50 @@ +/* eslint-disable no-undef */ +const supertest = require('supertest'); +const app = require('../app'); +const dbBuild = require('../database/config/build'); +const connection = require('../database/config/connection'); + +beforeEach(() => dbBuild()); +afterAll(() => connection.end()); + +describe('Tests login route to admin', () => { + test(' login route /login ', async () => { + const res = await supertest(app) + .post('/api/v1/admin/login') + .send({ + email: 'mohmsal96@gmail.com', + password: '1234567894455', + }) + .expect(200); + return expect(res.body).toEqual({ message: 'You are Logged Successfully' }); + }); + + test(' login route /login with error in email or password ', async () => { + const res = await supertest(app) + .post('/api/v1/admin/login') + .send({ + email: 'msal96@gmail.com', + password: '1234566', + }) + .expect(400); + return expect(res.body).toEqual({ message: 'Invalid email or password' }); + }); +}); + +describe('test signup as admin ', () => { + test('test sign up endpoint when success', async () => { + const res = await supertest(app) + .post('/api/v1/admin/signup') + .send({ + username: 'test', + password: 'test123456', + email: 'test@gmail.com', + }) + .expect(201) + .expect((response) => expect(response.header['set-cookie'][0].split('=')[0]).toBe('token')) + .expect('Content-Type', /json/); + return expect(res.body).toEqual({ + message: 'user created', + }); + }); +}); diff --git a/server/test/index.test.js b/server/test/agents.test.js similarity index 58% rename from server/test/index.test.js rename to server/test/agents.test.js index eedad0e..ff55444 100644 --- a/server/test/index.test.js +++ b/server/test/agents.test.js @@ -7,7 +7,7 @@ const connection = require('../database/config/connection'); beforeEach(() => dbBuild()); afterAll(() => connection.end()); -const userToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImthbGxwb3J0MEBwYXRjaC5jb20iLCJ1c2VySWQiOjEsImlhdCI6MTYzNTk0OTE4OX0.LjriIEoRDmj3_52PO8VlsaqekFiItE7gzamngrlaPDk'; +const userToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEifQ.ABHyuVZkr37lK6lelg18vAFAApbMj6KGTGhEbm9ROg4'; describe('Get all users', () => { test('get all users', async () => { @@ -15,7 +15,7 @@ describe('Get all users', () => { .get('/api/v1/user') .expect(200) .expect('Content-Type', /json/); - return expect(3).toEqual(res.body.data.length); + return expect(5).toEqual(res.body.data.length); }); }); @@ -43,30 +43,6 @@ describe('Tests login route', () => { }); }); -describe('Tests login route to admin', () => { - test(' login route /login ', async () => { - const res = await supertest(app) - .post('/api/v1/admin/login') - .send({ - email: 'mohmsal96@gmail.com', - password: '1234567894455', - }) - .expect(200); - return expect(res.body).toEqual({ message: 'You are Logged Successfully' }); - }); - - test(' login route /login with error in email or password ', async () => { - const res = await supertest(app) - .post('/api/v1/admin/login') - .send({ - email: 'msal96@gmail.com', - password: '1234566', - }) - .expect(400); - return expect(res.body).toEqual({ message: 'Invalid email or password' }); - }); -}); - describe('user estates', () => { test('get users estates', async () => { const res = await supertest(app) @@ -78,21 +54,21 @@ describe('user estates', () => { { id: 3, agent_id: 3, - title: 'rhoncus sed vestibulum', - price: '84726.00', - description: 'massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in', - type: 'Buy', - category: 'House', + title: 'Amazing house in Galilee', + price: '847.00', + description: 'Big beautiful stonehouse with garden and balcony with breathtaking view. A large fireplace and cousy livingroom. A lot of plants and artistic decoration. Harashim lays on top of a mountain in Galilee. Great for relaxing vacation and sightseeing.', + type: 'sale', + category: 'villa', street: '0824 Mcguire Way', city: 'Kungshamn', - region: 'Sweden', + region: 'Galilee', bathrooms: 1, bedrooms: 3, rooms: 3, space: '235', approved: true, - rate: 5, - available: false, + rate: '5', + available: true, }, { id: 6, @@ -100,8 +76,8 @@ describe('user estates', () => { title: 'vestibulum ante ipsum primis', price: '194193.55', description: 'leo odio porttitor id consequat in consequat ut nulla sed', - type: 'Buy', - category: 'House', + type: 'sale', + category: 'whole house', street: '0891 7th Park', city: 'Álimos', region: 'Greece', @@ -110,7 +86,7 @@ describe('user estates', () => { rooms: 2, space: '174', approved: false, - rate: 1, + rate: '1', available: false, }, ], @@ -130,87 +106,6 @@ describe('user estates', () => { }); }); }); -describe('user estates', () => { - test('edit estates', async () => { - const res = await supertest(app) - .put('/api/v1/estate/3') - .send({ - title: '1', - price: 10, - description: 's', - type: 's', - category: 's', - street: 's', - city: 's', - region: 's', - bathrooms: 1, - bedrooms: 1, - rooms: 1, - space: 50, - available: false, - }) - .expect(200) - .expect('Content-Type', /json/); - return expect(res.body.message).toBe('Estate updated successfully'); - }); - - test('edit estates erorr', async () => { - const res = await supertest(app) - .put('/api/v1/estate/350') - .send({ - title: '1', - price: 10, - description: 's', - type: 's', - category: 's', - street: 's', - city: 's', - region: 's', - bathrooms: 1, - bedrooms: 1, - rooms: 1, - space: 50, - available: false, - }) - .expect(400) - .expect('Content-Type', /json/); - return expect(res.body.message).toBe('enter valid estate id '); - }); -}); - -describe('Delete Specific Estate By Using Id', () => { - test('/estate/:estateId status 200 ', async () => { - const res = await supertest(app) - .delete('/api/v1/estate/1') - .set('Cookie', [`token=${userToken}`]) - .expect(200) - .expect('Content-Type', /json/); - return expect(res.body).toEqual({ - message: 'Estate deleted successfully', - }); - }); - test('/estate/:estateId status 400, when delete the same estate was deleted or not found ', async () => { - const res = await supertest(app) - .delete('/api/v1/estate/100') - .set('Cookie', [`token=${userToken}`]) - .expect(400) - .expect('Content-Type', /json/); - return expect(res.body).toEqual({ - message: 'You can\'t complete this process at the moment', - }); - }); - test('/estate/:estateId status 400, Invalid estate id ', async () => { - const res = await supertest(app) - .delete('/api/v1/estate/-121') - .set('Cookie', [`token=${userToken}`]) - .expect(400) - .expect('Content-Type', /json/); - return expect(res.body).toEqual({ - message: 'Invalid estate id', - }); - }); -}); - describe('test signup endpoint with all cases ', () => { test('test sign up endpoint when success', async () => { const res = await supertest(app) @@ -229,7 +124,6 @@ describe('test signup endpoint with all cases ', () => { message: 'user created', }); }); - test('test signup error validation phone" length must be 10 characters long ', async () => { const res = await supertest(app) .post('/api/v1/user/signup') @@ -280,7 +174,6 @@ describe('test signup endpoint with all cases ', () => { }); }); }); - describe('test Edit Agent data /user/:iduser ', () => { test('test 200', async () => { const res = await supertest(app) @@ -313,7 +206,7 @@ describe('test Edit Agent data /user/:iduser ', () => { message: '"phone" length must be at least 9 characters long', }); }); - test('test 404', async () => { + test('test 400 when user unknown get token for another user ', async () => { const res = await supertest(app) .put('/api/v1/user') .set('Cookie', ['token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im1hdTdhbW1hZGFiZWRAZ21haWwuY29tIiwidXNlcklkIjo0LCJpYXQiOjE2MzU5NDkyNTl9.St177PIpsDIHAVke6PxoGC8_cJmUrggpyhEcJ4QWKfI']) @@ -322,28 +215,10 @@ describe('test Edit Agent data /user/:iduser ', () => { email: 'kallport0@patch.com', phone: '059915587555', }) - .expect(404) + .expect(401) .expect('Content-Type', /json/); return expect(res.body).toEqual({ - message: 'There\'s no Agent, put correct id', - }); - }); -}); - -describe('test signup as admin ', () => { - test('test sign up endpoint when success', async () => { - const res = await supertest(app) - .post('/api/v1/admin/signup') - .send({ - username: 'test', - password: 'test123456', - email: 'test@gmail.com', - }) - .expect(201) - .expect((response) => expect(response.header['set-cookie'][0].split('=')[0]).toBe('token')) - .expect('Content-Type', /json/); - return expect(res.body).toEqual({ - message: 'user created', + message: 'You are not authorized ', }); }); }); diff --git a/server/test/estates.test.js b/server/test/estates.test.js new file mode 100644 index 0000000..c72653d --- /dev/null +++ b/server/test/estates.test.js @@ -0,0 +1,90 @@ +/* eslint-disable no-undef */ +const supertest = require('supertest'); +const app = require('../app'); +const dbBuild = require('../database/config/build'); +const connection = require('../database/config/connection'); + +const userToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEifQ.ABHyuVZkr37lK6lelg18vAFAApbMj6KGTGhEbm9ROg4'; + +beforeEach(() => dbBuild()); +afterAll(() => connection.end()); +test('edit estates erorr', async () => { + const res = await supertest(app) + .put('/api/v1/estate/350') + .send({ + title: '1', + price: 10, + description: 's', + type: 's', + category: 's', + street: 's', + city: 's', + region: 's', + bathrooms: 1, + bedrooms: 1, + rooms: 1, + space: 50, + available: false, + }) + .expect(400) + .expect('Content-Type', /json/); + return expect(res.body.message).toBe('enter valid estate id '); +}); + +describe('Delete Specific Estate By Using Id', () => { + test('/estate/:estateId status 200 ', async () => { + const res = await supertest(app) + .delete('/api/v1/estate/1') + .set('Cookie', [`token=${userToken}`]) + .expect(200) + .expect('Content-Type', /json/); + return expect(res.body).toEqual({ + message: 'Estate deleted successfully', + }); + }); + test('/estate/:estateId status 400, when delete the same estate was deleted or not found ', async () => { + const res = await supertest(app) + .delete('/api/v1/estate/100') + .set('Cookie', [`token=${userToken}`]) + .expect(400) + .expect('Content-Type', /json/); + return expect(res.body).toEqual({ + message: 'You can\'t complete this process at the moment', + }); + }); + test('/estate/:estateId status 400, Invalid estate id ', async () => { + const res = await supertest(app) + .delete('/api/v1/estate/-121') + .set('Cookie', [`token=${userToken}`]) + .expect(400) + .expect('Content-Type', /json/); + return expect(res.body).toEqual({ + message: 'Invalid estate id', + }); + }); +}); + +describe('user estates', () => { + test('edit estates', async () => { + const res = await supertest(app) + .put('/api/v1/estate/3') + .send({ + title: '1', + price: 10, + description: 's', + type: 's', + category: 's', + street: 's', + city: 's', + region: 's', + bathrooms: 1, + bedrooms: 1, + rooms: 1, + space: 50, + available: false, + }) + .expect(200) + .expect('Content-Type', /json/); + return expect(res.body.message).toBe('Estate updated successfully'); + }); +}); From 857e09d2c1240c853f36546577c8ee1c820ef1b3 Mon Sep 17 00:00:00 2001 From: Muhammad Abdulhadi Date: Fri, 5 Nov 2021 12:52:38 +0200 Subject: [PATCH 30/36] Update server/controllers/users/putAgent.js --- server/controllers/users/putAgent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/controllers/users/putAgent.js b/server/controllers/users/putAgent.js index 1aaa0a7..a0f8cc6 100644 --- a/server/controllers/users/putAgent.js +++ b/server/controllers/users/putAgent.js @@ -3,7 +3,7 @@ const editAgentSchema = require('../../utils/validation/editAgentSchema'); module.exports = async (req, res, next) => { try { - const { id: userId } = req.user; + const { userId } = req.user; const { error, value } = editAgentSchema.validate({ ...req.body, userId }); if (error) return res.status(400).json({ message: error.details[0].message }); const { rowCount } = await putAgent(value); From 28303aa1ba3517737939b31ace6eec46fadd9f8a Mon Sep 17 00:00:00 2001 From: Muhammad Abdulhadi Date: Fri, 5 Nov 2021 13:37:09 +0200 Subject: [PATCH 31/36] Edit tests token and fix jest problem --- client/package.json | 6 +----- package.json | 2 +- server/test/agents.test.js | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/client/package.json b/client/package.json index 09c5c78..da2dbf9 100644 --- a/client/package.json +++ b/client/package.json @@ -8,17 +8,13 @@ "@emotion/styled": "^11.3.0", "@mui/material": "^5.0.4", "@mui/styles": "^5.0.2", - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^11.2.7", - "@testing-library/user-event": "^12.8.3", "axios": "^0.23.0", "eslint-config-react-app": "^6.0.0", "react": "^17.0.2", "react-dom": "^17.0.2", "react-icons": "^4.3.1", "react-router-dom": "^5.3.0", - "react-scripts": "4.0.3", - "web-vitals": "^1.1.2" + "react-scripts": "4.0.3" }, "scripts": { "start": "react-scripts start", diff --git a/package.json b/package.json index 71cba01..1b37f5b 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "eslint": "^7.32.0", "eslint-config-airbnb-base": "^14.2.1", "eslint-plugin-import": "^2.25.2", - "jest": "^27.3.1", + "jest": "26.6.0", "nodemon": "^2.0.14", "pre-commit": "^1.2.2", "supertest": "^6.1.6" diff --git a/server/test/agents.test.js b/server/test/agents.test.js index ff55444..cbfcb96 100644 --- a/server/test/agents.test.js +++ b/server/test/agents.test.js @@ -7,7 +7,7 @@ const connection = require('../database/config/connection'); beforeEach(() => dbBuild()); afterAll(() => connection.end()); -const userToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEifQ.ABHyuVZkr37lK6lelg18vAFAApbMj6KGTGhEbm9ROg4'; +const userToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImthbGxwb3J0MEBwYXRjaC5jb20iLCJ1c2VySWQiOjEsImlhdCI6MTYzNjExMjAwNH0.o4iDQMffvwmqt47SDb5RifHWBSBK9FyG55cBN_QfcfQ'; describe('Get all users', () => { test('get all users', async () => { From 53e58035f9a6e06a6ab8fd22965a31221bf5724b Mon Sep 17 00:00:00 2001 From: Muhammad Abdulhadi Date: Fri, 5 Nov 2021 14:59:13 +0200 Subject: [PATCH 32/36] Fix Footer --- client/src/components/Footer/data.js | 2 +- client/src/components/Footer/index.js | 12 +++++----- client/src/components/Footer/style.css | 31 ++++++++++---------------- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/client/src/components/Footer/data.js b/client/src/components/Footer/data.js index ae1f079..f9666d3 100644 --- a/client/src/components/Footer/data.js +++ b/client/src/components/Footer/data.js @@ -42,7 +42,7 @@ const data = [ ], }, { - title: 'contact-us', + title: 'Contact us', links: [ { href: '/', diff --git a/client/src/components/Footer/index.js b/client/src/components/Footer/index.js index 9b6bafe..b685a2e 100644 --- a/client/src/components/Footer/index.js +++ b/client/src/components/Footer/index.js @@ -13,7 +13,7 @@ export default function Footer() { color="primary" sx={{ top: 'auto', bottom: 0 }} style={{ - background: '#3381CB', height: '432px', alignItems: 'center', + background: '#3381CB', alignItems: 'center', }} > @@ -35,16 +33,16 @@ export default function Footer() { />
-
+
{ - data.map(({ title, links }) => ( -
+ data.map(({ title, links }, i) => ( +

{title}

{ links.map(({ href, name, children }) => ( - + {children} {name} diff --git a/client/src/components/Footer/style.css b/client/src/components/Footer/style.css index 9465b74..4ff9a29 100644 --- a/client/src/components/Footer/style.css +++ b/client/src/components/Footer/style.css @@ -1,41 +1,30 @@ .section2 { display: flex; - width: 50%; + width: 60%; height: 100%; align-content: center; justify-content: space-around; - align-items: center; + align-items: flex-start; + margin-top: 30px; } -.about-us, -.services, -.contact-us, -.social { +.footer--list { display: flex; flex-direction: column; height: 50%; } -.about-us > a, -.services > a, -.contact-us > a, -.social > a { +.footer--list > a { font-size: 24px; margin-bottom: 20px; font-size: 18px; text-align: left; } -.about-us > a > svg, -.services > a > svg, -.contact-us > a > svg, -.social > a > svg { +.footer--list > a > svg { margin-right: 5px; } -.about-us > p, -.services > p, -.contact-us > p, -.social > p { +.footer--list > p { font-size: 26px; color: #fff; margin-bottom: 40px; @@ -43,8 +32,12 @@ text-align: left; } -.social * { +.Social * { display: flex; align-items: center; margin-left: 10px; } + +.footer { + background-color: black; +} \ No newline at end of file From 0f02d725df1ee3b32f579f75c78b0fd00920762d Mon Sep 17 00:00:00 2001 From: Muhammad Abdulhadi Date: Fri, 5 Nov 2021 15:00:41 +0200 Subject: [PATCH 33/36] Update client/src/components/Footer/style.css --- client/src/components/Footer/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/Footer/style.css b/client/src/components/Footer/style.css index 4ff9a29..3f7efd0 100644 --- a/client/src/components/Footer/style.css +++ b/client/src/components/Footer/style.css @@ -40,4 +40,4 @@ .footer { background-color: black; -} \ No newline at end of file +} From 1a5be00f911cd338c0ade86afdd474d322b60ad6 Mon Sep 17 00:00:00 2001 From: muhammadharoun Date: Sun, 7 Nov 2021 10:12:11 +0200 Subject: [PATCH 34/36] Changes Requested --- client/package.json | 1 + .../src/components/UserContacatCard/index.js | 27 +++++++++++++------ .../UserContacatCard/userContactCard.css | 0 package.json | 2 +- 4 files changed, 21 insertions(+), 9 deletions(-) delete mode 100644 client/src/components/UserContacatCard/userContactCard.css diff --git a/client/package.json b/client/package.json index c46c94b..1a91585 100644 --- a/client/package.json +++ b/client/package.json @@ -11,6 +11,7 @@ "@mui/styles": "^5.0.2", "axios": "^0.23.0", "eslint-config-react-app": "^6.0.0", + "prop-types": "^15.7.2", "react": "^17.0.2", "react-dom": "^17.0.2", "react-icons": "^4.3.1", diff --git a/client/src/components/UserContacatCard/index.js b/client/src/components/UserContacatCard/index.js index 72854c2..62da8e2 100644 --- a/client/src/components/UserContacatCard/index.js +++ b/client/src/components/UserContacatCard/index.js @@ -10,6 +10,7 @@ import MdPhone from '@mui/icons-material/Phone'; import LocationOnIcon from '@mui/icons-material/LocationOn'; import EmailIcon from '@mui/icons-material/Email'; import { makeStyles } from '@mui/styles'; +import PropTypes from 'prop-types'; const useStyles = makeStyles({ card: { @@ -26,9 +27,8 @@ const useStyles = makeStyles({ }, }); const contentStyles = { display: 'flex', marginBottom: '15px', alignItems: 'center' }; -function UserContactCard({ - image, name, location, phone, email, -}) { + +function UserContactCard({ data }) { const classes = useStyles(); return ( @@ -36,12 +36,12 @@ function UserContactCard({ - {name} + {data.name} Building Owner @@ -52,17 +52,17 @@ function UserContactCard({ - {location} + {data.location} - {phone} + {data.phone} - {email} + {data.email} @@ -70,4 +70,15 @@ function UserContactCard({ ); } +// Your Code here + +UserContactCard.propTypes = { + data: PropTypes.shape({ + image: PropTypes.string, + name: PropTypes.string, + location: PropTypes.string, + phone: PropTypes.string, + email: PropTypes.string, + }).isRequired, +}; export default UserContactCard; diff --git a/client/src/components/UserContacatCard/userContactCard.css b/client/src/components/UserContacatCard/userContactCard.css deleted file mode 100644 index e69de29..0000000 diff --git a/package.json b/package.json index 1b37f5b..f747cc1 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "joi": "^17.4.2", "jsonwebtoken": "^8.5.1", "pg": "^8.7.1" - }, + }, "devDependencies": { "eslint": "^7.32.0", "eslint-config-airbnb-base": "^14.2.1", From 5d4e5a8cc2417c1fff13a7296c2ddaf14d434884 Mon Sep 17 00:00:00 2001 From: muhammadharoun Date: Sun, 7 Nov 2021 10:56:24 +0200 Subject: [PATCH 35/36] remove comment --- client/src/components/UserContacatCard/index.js | 3 +-- test.js | 0 2 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 test.js diff --git a/client/src/components/UserContacatCard/index.js b/client/src/components/UserContacatCard/index.js index 62da8e2..282d54e 100644 --- a/client/src/components/UserContacatCard/index.js +++ b/client/src/components/UserContacatCard/index.js @@ -70,8 +70,6 @@ function UserContactCard({ data }) { ); } -// Your Code here - UserContactCard.propTypes = { data: PropTypes.shape({ image: PropTypes.string, @@ -81,4 +79,5 @@ UserContactCard.propTypes = { email: PropTypes.string, }).isRequired, }; + export default UserContactCard; diff --git a/test.js b/test.js new file mode 100644 index 0000000..e69de29 From bca9f7a301d17eaf0fe8435021ddb1641dfbe759 Mon Sep 17 00:00:00 2001 From: muhammadharoun Date: Sun, 7 Nov 2021 11:03:34 +0200 Subject: [PATCH 36/36] add changes --- client/src/components/UserContacatCard/index.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/client/src/components/UserContacatCard/index.js b/client/src/components/UserContacatCard/index.js index 282d54e..1d16b0c 100644 --- a/client/src/components/UserContacatCard/index.js +++ b/client/src/components/UserContacatCard/index.js @@ -28,7 +28,11 @@ const useStyles = makeStyles({ }); const contentStyles = { display: 'flex', marginBottom: '15px', alignItems: 'center' }; -function UserContactCard({ data }) { +function UserContactCard({ + data: { + name, phone, image, location, email, + }, +}) { const classes = useStyles(); return ( @@ -36,12 +40,12 @@ function UserContactCard({ data }) { - {data.name} + {name} Building Owner @@ -52,17 +56,17 @@ function UserContactCard({ data }) { - {data.location} + {location} - {data.phone} + {phone} - {data.email} + {email}