diff --git a/backend/migrations/20241210225728-add-action-url-banner.js b/backend/migrations/20241210225728-add-action-url-banner.js new file mode 100644 index 00000000..949f5c67 --- /dev/null +++ b/backend/migrations/20241210225728-add-action-url-banner.js @@ -0,0 +1,18 @@ +"use strict"; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.addColumn("banners", "actionUrl", { + type: Sequelize.STRING, + allowNull: true, + validate: { + isUrl: true, + }, + }); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.removeColumn("banners", "actionUrl"); + }, +}; diff --git a/backend/migrations/20241210225734-add-action-url-popup.js b/backend/migrations/20241210225734-add-action-url-popup.js new file mode 100644 index 00000000..cd07d11a --- /dev/null +++ b/backend/migrations/20241210225734-add-action-url-popup.js @@ -0,0 +1,18 @@ +"use strict"; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.addColumn("popup", "actionUrl", { + type: Sequelize.STRING, + allowNull: true, + validate: { + isUrl: true, + }, + }); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.removeColumn("popup", "actionUrl"); + }, +}; diff --git a/backend/src/controllers/banner.controller.js b/backend/src/controllers/banner.controller.js index ad6994c2..ccc92855 100644 --- a/backend/src/controllers/banner.controller.js +++ b/backend/src/controllers/banner.controller.js @@ -1,33 +1,61 @@ const bannerService = require("../service/banner.service.js"); const { internalServerError } = require("../utils/errors.helper"); const { validateCloseButtonAction } = require("../utils/guide.helper"); -const { validatePosition } = require("../utils/banner.helper"); +const { + validatePosition, + validateUrl, + validateRelativeUrl, +} = require("../utils/banner.helper"); const { checkColorFieldsFail } = require("../utils/guide.helper"); class BannerController { async addBanner(req, res) { const userId = req.user.id; - const { position, closeButtonAction, fontColor, backgroundColor } = req.body; + const { + position, + closeButtonAction, + fontColor, + backgroundColor, + actionUrl, + url, + } = req.body; if (!position || !closeButtonAction) { - return res - .status(400) - .json({ - errors: [{ msg: "position and closeButtonAction are required" }], - }); + return res.status(400).json({ + errors: [{ msg: "position and closeButtonAction are required" }], + }); } - if (!validatePosition(position) || !validateCloseButtonAction(closeButtonAction)) { - return res - .status(400) - .json({ - errors: [{ msg: "Invalid value entered" }], - }); + if ( + !validatePosition(position) || + !validateCloseButtonAction(closeButtonAction) + ) { + return res.status(400).json({ + errors: [{ msg: "Invalid value entered" }], + }); + } + + if (actionUrl) { + try { + validateUrl(actionUrl, "actionUrl"); + } catch (err) { + return res.status(400).json({ errors: [{ msg: err.message }] }); + } + } + + if (url) { + try { + validateRelativeUrl(url, "url"); + } catch (err) { + return res.status(400).json({ errors: [{ msg: err.message }] }); + } } const colorFields = { fontColor, backgroundColor }; - const colorCheck = checkColorFieldsFail(colorFields, res) - if (colorCheck) { return colorCheck }; + const colorCheck = checkColorFieldsFail(colorFields, res); + if (colorCheck) { + return colorCheck; + } try { const newBannerData = { ...req.body, createdBy: userId }; @@ -37,7 +65,7 @@ class BannerController { console.log(err); const { statusCode, payload } = internalServerError( "CREATE_BANNER_ERROR", - err.message, + err.message ); res.status(statusCode).json(payload); } @@ -54,11 +82,9 @@ class BannerController { const deletionResult = await bannerService.deleteBanner(id); if (!deletionResult) { - return res - .status(400) - .json({ - errors: [{ msg: "Banner with the specified id does not exist" }], - }); + return res.status(400).json({ + errors: [{ msg: "Banner with the specified id does not exist" }], + }); } res @@ -67,7 +93,7 @@ class BannerController { } catch (err) { const { statusCode, payload } = internalServerError( "DELETE_BANNER_ERROR", - err.message, + err.message ); res.status(statusCode).json(payload); } @@ -76,14 +102,19 @@ class BannerController { async editBanner(req, res) { try { const { id } = req.params; - const { fontColor, backgroundColor, url, position, closeButtonAction, bannerText } = req.body; + const { + fontColor, + backgroundColor, + url, + position, + closeButtonAction, + actionUrl, + } = req.body; if (!position || !closeButtonAction) { - return res - .status(400) - .json({ - errors: [{ msg: "position and closeButtonAction are required" }], - }); + return res.status(400).json({ + errors: [{ msg: "position and closeButtonAction are required" }], + }); } if (!validatePosition(position)) { @@ -98,16 +129,34 @@ class BannerController { .json({ errors: [{ msg: "Invalid value for closeButtonAction" }] }); } + if (actionUrl) { + try { + validateUrl(actionUrl, "actionUrl"); + } catch (err) { + return res.status(400).json({ errors: [{ msg: err.message }] }); + } + } + + if (url) { + try { + validateRelativeUrl(url, "url"); + } catch (err) { + return res.status(400).json({ errors: [{ msg: err.message }] }); + } + } + const colorFields = { fontColor, backgroundColor }; - const colorCheck = checkColorFieldsFail(colorFields, res) - if (colorCheck) { return colorCheck }; + const colorCheck = checkColorFieldsFail(colorFields, res); + if (colorCheck) { + return colorCheck; + } const updatedBanner = await bannerService.updateBanner(id, req.body); res.status(200).json(updatedBanner); } catch (err) { const { statusCode, payload } = internalServerError( "EDIT_BANNER_ERROR", - err.message, + err.message ); res.status(statusCode).json(payload); } @@ -120,7 +169,7 @@ class BannerController { } catch (err) { const { statusCode, payload } = internalServerError( "GET_ALL_BANNERS_ERROR", - err.message, + err.message ); res.status(statusCode).json(payload); } @@ -133,8 +182,8 @@ class BannerController { res.status(200).json(banners); } catch (err) { const { statusCode, payload } = internalServerError( - "GET\_BANNERS_ERROR", - err.message, + "GET_BANNERS_ERROR", + err.message ); res.status(statusCode).json(payload); } @@ -158,7 +207,7 @@ class BannerController { } catch (err) { const { statusCode, payload } = internalServerError( "GET_BANNER_BY_ID_ERROR", - err.message, + err.message ); res.status(statusCode).json(payload); } @@ -167,19 +216,22 @@ class BannerController { try { const { url } = req.body; - if (!url || typeof url !== 'string' ) { - return res.status(400).json({ errors: [{ msg: "URL is missing or invalid" }] }); + if (!url || typeof url !== "string") { + return res + .status(400) + .json({ errors: [{ msg: "URL is missing or invalid" }] }); } const banner = await bannerService.getBannerByUrl(url); - res.status(200).json({banner}); + res.status(200).json({ banner }); } catch (error) { - internalServerError( + const { payload, statusCode } = internalServerError( "GET_BANNER_BY_URL_ERROR", - error.message, + error.message ); + res.status(statusCode).json(payload); } - }; + } } module.exports = new BannerController(); diff --git a/backend/src/controllers/popup.controller.js b/backend/src/controllers/popup.controller.js index d1c6f050..0a566696 100644 --- a/backend/src/controllers/popup.controller.js +++ b/backend/src/controllers/popup.controller.js @@ -1,8 +1,12 @@ const popupService = require("../service/popup.service"); const { internalServerError } = require("../utils/errors.helper"); -const {validateCloseButtonAction } = require("../utils/guide.helper"); -const { validatePopupSize } = require("../utils/popup.helper"); -const { checkColorFieldsFail } =require("../utils/guide.helper"); +const { validateCloseButtonAction } = require("../utils/guide.helper"); +const { + validatePopupSize, + validateUrl, + validateRelativeUrl, +} = require("../utils/popup.helper"); +const { checkColorFieldsFail } = require("../utils/guide.helper"); class PopupController { async addPopup(req, res) { @@ -15,27 +19,42 @@ class PopupController { textColor, buttonBackgroundColor, buttonTextColor, + actionUrl, + url, } = req.body; if (!popupSize || !closeButtonAction) { - return res - .status(400) - .json({ - errors: [{ msg: "popupSize and closeButtonAction are required" }], - }); + return res.status(400).json({ + errors: [{ msg: "popupSize and closeButtonAction are required" }], + }); } if ( !validatePopupSize(popupSize) || !validateCloseButtonAction(closeButtonAction) ) { - return res - .status(400) - .json({ - errors: [{ msg: "Invalid value for popupSize or closeButtonAction" }], - }); + return res.status(400).json({ + errors: [{ msg: "Invalid value for popupSize or closeButtonAction" }], + }); } + if (actionUrl) { + try { + validateUrl(actionUrl, "actionUrl"); + } catch (err) { + return res.status(400).json({ errors: [{ msg: err.message }] }); + } + } + + if (url) { + try { + validateRelativeUrl(url, "url"); + } catch (err) { + return res.status(400).json({ errors: [{ msg: err.message }] }); + } + } + + const colorFields = { headerBackgroundColor, headerColor, @@ -43,8 +62,10 @@ class PopupController { buttonBackgroundColor, buttonTextColor, }; - const colorCheck = checkColorFieldsFail(colorFields, res) - if(colorCheck){return colorCheck}; + const colorCheck = checkColorFieldsFail(colorFields, res); + if (colorCheck) { + return colorCheck; + } try { const newPopupData = { ...req.body, createdBy: userId }; @@ -54,7 +75,7 @@ class PopupController { console.log(err); const { statusCode, payload } = internalServerError( "CREATE_POPUP_ERROR", - err.message, + err.message ); res.status(statusCode).json(payload); } @@ -64,18 +85,16 @@ class PopupController { try { const { id } = req.params; - if (Number.isNaN(Number(id)) || id.trim() === "") { + if (Number.isNaN(Number(id)) || id.trim() === "") { return res.status(400).json({ errors: [{ msg: "Invalid id" }] }); } const deletionResult = await popupService.deletePopup(id); if (!deletionResult) { - return res - .status(400) - .json({ - errors: [{ msg: "Popup with the specified id does not exist" }], - }); + return res.status(400).json({ + errors: [{ msg: "Popup with the specified id does not exist" }], + }); } res @@ -84,7 +103,7 @@ class PopupController { } catch (err) { const { statusCode, payload } = internalServerError( "DELETE_POPUP_ERROR", - err.message, + err.message ); res.status(statusCode).json(payload); } @@ -93,14 +112,22 @@ class PopupController { async editPopup(req, res) { try { const { id } = req.params; - const { popupSize, closeButtonAction, headerBackgroundColor, headerColor, textColor, buttonBackgroundColor, buttonTextColor } = req.body; + const { + popupSize, + closeButtonAction, + headerBackgroundColor, + headerColor, + textColor, + buttonBackgroundColor, + buttonTextColor, + actionUrl, + url, + } = req.body; if (!popupSize || !closeButtonAction) { - return res - .status(400) - .json({ - errors: [{ msg: "popupSize and closeButtonAction are required" }], - }); + return res.status(400).json({ + errors: [{ msg: "popupSize and closeButtonAction are required" }], + }); } if (!validatePopupSize(popupSize)) { @@ -115,6 +142,22 @@ class PopupController { .json({ errors: [{ msg: "Invalid value for closeButtonAction" }] }); } + if (actionUrl) { + try { + validateUrl(actionUrl, "actionUrl"); + } catch (err) { + return res.status(400).json({ errors: [{ msg: err.message }] }); + } + } + + if (url) { + try { + validateRelativeUrl(url, "url"); + } catch (err) { + return res.status(400).json({ errors: [{ msg: err.message }] }); + } + } + const colorFields = { headerBackgroundColor, headerColor, @@ -122,21 +165,22 @@ class PopupController { buttonBackgroundColor, buttonTextColor, }; - const colorCheck = checkColorFieldsFail(colorFields, res) - if(colorCheck){return colorCheck}; + const colorCheck = checkColorFieldsFail(colorFields, res); + if (colorCheck) { + return colorCheck; + } const updatedPopup = await popupService.updatePopup(id, req.body); res.status(200).json(updatedPopup); } catch (err) { const { statusCode, payload } = internalServerError( "EDIT_POPUP_ERROR", - err.message, + err.message ); res.status(statusCode).json(payload); } } - async getAllPopups(req, res) { try { const popups = await popupService.getAllPopups(); @@ -144,7 +188,7 @@ class PopupController { } catch (err) { const { statusCode, payload } = internalServerError( "GET_ALL_POPUPS_ERROR", - err.message, + err.message ); res.status(statusCode).json(payload); } @@ -158,7 +202,7 @@ class PopupController { } catch (err) { const { statusCode, payload } = internalServerError( "GET_POPUPS_ERROR", - err.message, + err.message ); res.status(statusCode).json(payload); } @@ -168,23 +212,21 @@ class PopupController { try { const { id } = req.params; - if (Number.isNaN(Number(id)) || id.trim() === "") { + if (Number.isNaN(Number(id)) || id.trim() === "") { return res.status(400).json({ errors: [{ msg: "Invalid popup ID" }] }); } const popup = await popupService.getPopupById(id); if (!popup) { - return res - .status(404) - .json({ errors: [{ msg: "Popup not found" }] }); + return res.status(404).json({ errors: [{ msg: "Popup not found" }] }); } res.status(200).json(popup); } catch (err) { const { statusCode, payload } = internalServerError( "GET_POPUP_BY_ID_ERROR", - err.message, + err.message ); res.status(statusCode).json(payload); } @@ -193,20 +235,22 @@ class PopupController { try { const { url } = req.body; - if (!url || typeof url !== 'string' ) { - return res.status(400).json({ errors: [{ msg: "URL is missing or invalid" }] }); + if (!url || typeof url !== "string") { + return res + .status(400) + .json({ errors: [{ msg: "URL is missing or invalid" }] }); } const popup = await popupService.getPopupByUrl(url); - res.status(200).json({popup}); + res.status(200).json({ popup }); } catch (error) { - internalServerError( + const { payload, statusCode } = internalServerError( "GET_POPUP_BY_URL_ERROR", - error.message, + error.message ); + res.status(statusCode).json(payload); } - }; - + } } -module.exports = new PopupController(); \ No newline at end of file +module.exports = new PopupController(); diff --git a/backend/src/models/Banner.js b/backend/src/models/Banner.js index 23d9124b..6655ab5d 100644 --- a/backend/src/models/Banner.js +++ b/backend/src/models/Banner.js @@ -1,74 +1,96 @@ -const { validateHexColor, validateActionButton } = require('../utils/guide.helper'); -const { validatePositionWrapper } = require('../utils/banner.helper'); +const { + validateHexColor, + validateActionButton, +} = require("../utils/guide.helper"); +const { + validatePositionWrapper, + validateUrl, + validateRelativeUrl, +} = require("../utils/banner.helper"); module.exports = (sequelize, DataTypes) => { - const Banner = sequelize.define('Banner', { - closeButtonAction: { - type: DataTypes.STRING, - allowNull: false, - validate: { - isValidAction(value) { - validateActionButton(value); - }, - }, + const Banner = sequelize.define( + "Banner", + { + closeButtonAction: { + type: DataTypes.STRING, + allowNull: false, + validate: { + isValidAction(value) { + validateActionButton(value); }, - position: { - type: DataTypes.STRING, - allowNull: false, - validate: { - isValidPosition(value) { - validatePositionWrapper(value); - }, - }, + }, + }, + position: { + type: DataTypes.STRING, + allowNull: false, + validate: { + isValidPosition(value) { + validatePositionWrapper(value); }, - url: { - type: DataTypes.STRING, - allowNull: true, + }, + }, + url: { + type: DataTypes.STRING, + allowNull: true, + validate: { + isUrl(value) { + validateRelativeUrl(value, "url"); }, - fontColor: { - type: DataTypes.STRING, - allowNull: false, - defaultValue: "#FFFFFF", - validate: { - isHexColor(value) { - validateHexColor(value, 'fontColor'); - }, - }, + }, + }, + fontColor: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: "#FFFFFF", + validate: { + isHexColor(value) { + validateHexColor(value, "fontColor"); }, - backgroundColor: { - type: DataTypes.STRING, - allowNull: false, - defaultValue: "#FFFFFF", - validate: { - isHexColor(value) { - validateHexColor(value, 'backgroundColor'); - }, - }, + }, + }, + backgroundColor: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: "#FFFFFF", + validate: { + isHexColor(value) { + validateHexColor(value, "backgroundColor"); }, - bannerText: { - type: DataTypes.STRING, - allowNull: false, - defaultValue: "", + }, + }, + bannerText: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: "", + }, + actionUrl: { + type: DataTypes.STRING, + allowNull: true, + validate: { + isUrl(value) { + validateUrl(value, "actionUrl"); }, + }, + }, - createdBy: { - type: DataTypes.INTEGER, - allowNull: false, - references: { - model: "users", - key: "id", - }, + createdBy: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: "users", + key: "id", }, + }, }, - { - tableName: "banners", - timestamps: false, - }, - ); + { + tableName: "banners", + timestamps: false, + } + ); - Banner.associate = (models) => { - Banner.belongsTo(models.User, { foreignKey: "createdBy", as: "creator" }); - }; - return Banner; + Banner.associate = (models) => { + Banner.belongsTo(models.User, { foreignKey: "createdBy", as: "creator" }); + }; + return Banner; }; - diff --git a/backend/src/models/Popup.js b/backend/src/models/Popup.js index f1b9719f..0e81dffa 100644 --- a/backend/src/models/Popup.js +++ b/backend/src/models/Popup.js @@ -1,5 +1,12 @@ -const { validateHexColor, validateActionButton } = require('../utils/guide.helper'); -const { validatePopupSizeWrapper } = require('../utils/popup.helper'); +const { + validateHexColor, + validateActionButton, +} = require("../utils/guide.helper"); +const { + validatePopupSizeWrapper, + validateUrl, + validateRelativeUrl, +} = require("../utils/popup.helper"); module.exports = (sequelize, DataTypes) => { const Popup = sequelize.define( @@ -15,7 +22,7 @@ module.exports = (sequelize, DataTypes) => { allowNull: false, validate: { isValidAction(value) { - validateActionButton(value); + validateActionButton(value); }, }, }, @@ -24,13 +31,18 @@ module.exports = (sequelize, DataTypes) => { allowNull: false, validate: { isValidPopupSize(value) { - validatePopupSizeWrapper(value); + validatePopupSizeWrapper(value); }, }, }, url: { type: DataTypes.STRING, allowNull: true, + validate: { + isUrl(value) { + validateRelativeUrl(value, "url"); + }, + }, }, actionButtonText: { type: DataTypes.STRING, @@ -42,7 +54,7 @@ module.exports = (sequelize, DataTypes) => { defaultValue: "#FFFFFF", validate: { isHexColor(value) { - validateHexColor(value, 'headerBackgroundColor'); + validateHexColor(value, "headerBackgroundColor"); }, }, }, @@ -52,7 +64,7 @@ module.exports = (sequelize, DataTypes) => { defaultValue: "#FFFFFF", validate: { isHexColor(value) { - validateHexColor(value, 'headerColor'); + validateHexColor(value, "headerColor"); }, }, }, @@ -62,7 +74,7 @@ module.exports = (sequelize, DataTypes) => { defaultValue: "#FFFFFF", validate: { isHexColor(value) { - validateHexColor(value, 'textColor'); + validateHexColor(value, "textColor"); }, }, }, @@ -72,7 +84,7 @@ module.exports = (sequelize, DataTypes) => { defaultValue: "#FFFFFF", validate: { isHexColor(value) { - validateHexColor(value, 'buttonBackgroundColor'); + validateHexColor(value, "buttonBackgroundColor"); }, }, }, @@ -82,7 +94,7 @@ module.exports = (sequelize, DataTypes) => { defaultValue: "#FFFFFF", validate: { isHexColor(value) { - validateHexColor(value, 'buttonTextColor'); + validateHexColor(value, "buttonTextColor"); }, }, }, @@ -96,6 +108,15 @@ module.exports = (sequelize, DataTypes) => { allowNull: false, defaultValue: "", }, + actionUrl: { + type: DataTypes.STRING, + allowNull: true, + validate: { + isUrl(value) { + validateUrl(value, "actionUrl"); + }, + }, + }, createdBy: { type: DataTypes.INTEGER, allowNull: false, @@ -108,7 +129,7 @@ module.exports = (sequelize, DataTypes) => { { tableName: "popup", timestamps: false, - }, + } ); Popup.associate = (models) => { diff --git a/backend/src/test/mocks/banner.mock.js b/backend/src/test/mocks/banner.mock.js index 1a88364c..d82af968 100644 --- a/backend/src/test/mocks/banner.mock.js +++ b/backend/src/test/mocks/banner.mock.js @@ -9,6 +9,7 @@ class BannerBuilder { backgroundColor: "#FFFFFF", bannerText: "banner 1", createdBy: 1, + actionUrl: "https://www.google.com", }; } diff --git a/backend/src/test/mocks/popup.mock.js b/backend/src/test/mocks/popup.mock.js index 12957914..75495073 100644 --- a/backend/src/test/mocks/popup.mock.js +++ b/backend/src/test/mocks/popup.mock.js @@ -14,6 +14,7 @@ class PopupBuilder { header: "header", content: "content", createdBy: 1, + actionUrl: "https://www.google.com", }; } diff --git a/backend/src/test/unit/controllers/popup.test.js b/backend/src/test/unit/controllers/popup.test.js index 990ec7b7..4eba0f6e 100644 --- a/backend/src/test/unit/controllers/popup.test.js +++ b/backend/src/test/unit/controllers/popup.test.js @@ -349,6 +349,7 @@ describe("Test popup controller", () => { await popupController.editPopup(req, res); const status = res.status.getCall(0).args[0]; const body = res.json.getCall(0).args[0]; + console.log(body) expect(status).to.be.equal(500); expect(body).to.be.deep.equal({ error: "Internal Server Error", diff --git a/backend/src/utils/banner.helper.js b/backend/src/utils/banner.helper.js index 5c23eb8c..93c42be8 100644 --- a/backend/src/utils/banner.helper.js +++ b/backend/src/utils/banner.helper.js @@ -5,12 +5,37 @@ const validatePosition = (value) => { const validatePositionWrapper = (value) => { if (!validatePosition(value)) { - throw new Error('Invalid position'); + throw new Error("Invalid position"); } }; - - module.exports = { - validatePosition, - validatePositionWrapper - }; \ No newline at end of file +const validateRelativeUrl = (value, fieldName) => { + if (!value) return; + try { + new URL(value); + } catch (error) { + if (value.startsWith('/')) { + return + } + throw new Error(`Invalid URL for ${fieldName}: ${error.message}`); + } +} + +const validateUrl = (value, fieldName) => { + if (!value) return; + try { + const url = new URL(value); + if (!["http:", "https:"].includes(url.protocol)) { + throw new Error("URL must use HTTP or HTTPS protocol"); + } + } catch (error) { + throw new Error(`Invalid URL for ${fieldName}: ${error.message}`); + } +}; + +module.exports = { + validatePosition, + validatePositionWrapper, + validateUrl, + validateRelativeUrl, +}; diff --git a/backend/src/utils/popup.helper.js b/backend/src/utils/popup.helper.js index 41d258a8..aff9cf03 100644 --- a/backend/src/utils/popup.helper.js +++ b/backend/src/utils/popup.helper.js @@ -9,9 +9,33 @@ const validatePopupSizeWrapper = (value) => { } }; +const validateRelativeUrl = (value, fieldName) => { + if (!value) return; + try { + new URL(value); + } catch (error) { + if (value.startsWith('/')) { + return + } + throw new Error(`Invalid URL for ${fieldName}: ${error.message}`); + } +} +const validateUrl = (value, fieldName) => { + if (!value) return; + try { + const url = new URL(value); + if (!['http:', 'https:'].includes(url.protocol)) { + throw new Error('URL must use HTTP or HTTPS protocol'); + } + } catch (error) { + throw new Error(`Invalid URL for ${fieldName}: ${error.message}`); + } +}; module.exports = { validatePopupSize, - validatePopupSizeWrapper + validatePopupSizeWrapper, + validateUrl, + validateRelativeUrl }; diff --git a/frontend/src/scenes/banner/BannerPageComponents/BannerLeftContent/BannerLeftContent.jsx b/frontend/src/scenes/banner/BannerPageComponents/BannerLeftContent/BannerLeftContent.jsx index 79a336d6..600d083c 100644 --- a/frontend/src/scenes/banner/BannerPageComponents/BannerLeftContent/BannerLeftContent.jsx +++ b/frontend/src/scenes/banner/BannerPageComponents/BannerLeftContent/BannerLeftContent.jsx @@ -1,54 +1,85 @@ -import React from 'react'; -import styles from './BannerLeftContent.module.scss'; -import DropdownList from '@components/DropdownList/DropdownList'; -import CustomTextField from '@components/TextFieldComponents/CustomTextField/CustomTextField'; -import RadioButton from '@components/RadioButton/RadioButton'; - -const BannerLeftContent = ({ setIsTopPosition, url, setUrl, setButtonAction, isTopPosition, buttonAction }) => { - const handleSetUrl = (event) => { - setUrl(event.target.value); - }; - - const handleActionChange = (newAction) => { - setButtonAction(newAction); - }; - - const handlePositionChange = (newPosition) => { - setIsTopPosition(newPosition); - }; - - return ( -