From 5c3af38ebc89b562a8893446d7a71be6fd487922 Mon Sep 17 00:00:00 2001 From: Pratish Ninawe Date: Fri, 22 Sep 2023 18:46:04 +0530 Subject: [PATCH 1/4] implemented functionality to upload files via spreadsheet also --- src/views/Campaigns/AddCampaign.js | 4 +- src/views/Campaigns/BasicDetaiils.js | 1 + src/views/Campaigns/ContactDetails.js | 335 +++++++++++++++++--------- src/views/Campaigns/Preview.js | 22 +- 4 files changed, 235 insertions(+), 127 deletions(-) diff --git a/src/views/Campaigns/AddCampaign.js b/src/views/Campaigns/AddCampaign.js index a0f224b..459fee9 100644 --- a/src/views/Campaigns/AddCampaign.js +++ b/src/views/Campaigns/AddCampaign.js @@ -138,7 +138,7 @@ const AddCampaign = () => { // }); // }; - console.log(data); + // console.log(data); return ( @@ -153,7 +153,7 @@ const AddCampaign = () => { " >
- Add Campaign + Contact Details
diff --git a/src/views/Campaigns/BasicDetaiils.js b/src/views/Campaigns/BasicDetaiils.js index 50d0981..15c5173 100644 --- a/src/views/Campaigns/BasicDetaiils.js +++ b/src/views/Campaigns/BasicDetaiils.js @@ -2,6 +2,7 @@ import React from "react"; import { useState } from "react"; import Button from "@material-ui/core/Button"; import toast from "react-hot-toast"; + const BasicDetaiils = ({ props }) => { const { data, setData, handleView } = props; diff --git a/src/views/Campaigns/ContactDetails.js b/src/views/Campaigns/ContactDetails.js index bd899bc..e2840b5 100644 --- a/src/views/Campaigns/ContactDetails.js +++ b/src/views/Campaigns/ContactDetails.js @@ -2,17 +2,56 @@ import React from "react"; import Button from "@material-ui/core/Button"; import { useState } from "react"; import toast from "react-hot-toast"; +import { CFormInput, CFormLabel, CCol, CRow } from "@coreui/react"; + const ContactDetails = ({ props }) => { const { data, setData, handleView } = props; + const [dataEntryMethod, setDataEntryMethod] = useState("manual"); + const [csvData, setCsvData] = useState([]); // const [recipients, setRecipients] = useState([{ name: "", phoneNumber: "" }]); - + // console.log("data", data); const addRecord = () => { setData((prevData) => ({ ...prevData, - recipients: [...prevData.recipients, { name: "", phoneNumber: "" }], + recipients: [ + ...prevData.recipients, + { name: "", phoneNumber: "", email: "" }, + ], })); }; + const handleSpreadSheet = (e) => { + const file = e.target.files[0]; + if (file) { + const reader = new FileReader(); + + reader.onload = (event) => { + const csvData = event.target.result; + const rows = csvData.split("\n"); + const extractedData = []; + + for (let i = 0; i < rows.length; i++) { + const row = rows[i].split(","); + if (row.length >= 2) { + const name = row[0].trim(); + const email = row[1].trim(); + if (name && email) { + extractedData.push({ name, email }); + } + } + } + setCsvData(extractedData); + console.log(csvData); + setData((prevData) => ({ + ...prevData, + recipients: extractedData, + spreadSheet: file.name, + })); + }; + reader.readAsText(file); + } + }; + const deleteRecipient = (index) => { const updatedRecipients = [...data.recipients]; updatedRecipients.splice(index, 1); @@ -46,131 +85,193 @@ const ContactDetails = ({ props }) => { })); }; + const recipientEmailChange = (e, index) => { + const updatedRecipients = [...data.recipients]; + updatedRecipients[index] = { + ...updatedRecipients[index], + email: e.target.value, + }; + setData((prevData) => ({ + ...prevData, + recipients: updatedRecipients, + })); + }; + + const handleSubmit = () => { + if ( + data?.recipients.every( + (recipient) => + recipient.name !== "" && + (data?.campaignType !== "email" + ? recipient.phoneNumber !== "" + : recipient.email !== "") + ) + ) { + handleView(3); + } else { + toast.error("Fill all contact details"); + } + }; + return (
-
-
-
-
- Contact Details -
-
-

-
- -
- - +
+
+
+
+
+ +
+
+ + +
- -
-
-
-
- {data?.recipients.map((recipient, index) => { - return ( -
-
+ )} + + {dataEntryMethod === "spreadsheet" && ( +
+
+ {/* Spreadsheet data entry form */} +
+
+
+
+ + handleSpreadSheet(e)} + /> +
+
+
+
+
+
+ )}
); diff --git a/src/views/Campaigns/Preview.js b/src/views/Campaigns/Preview.js index fe33526..de2e281 100644 --- a/src/views/Campaigns/Preview.js +++ b/src/views/Campaigns/Preview.js @@ -68,15 +68,21 @@ const Preview = ({ props }) => { {data?.campaignType} - Video + + {data?.campaignType === "email" ? "Video" : "Spreadsheet"} + - + {data?.campaignType === "email" ? ( + + ) : ( +
{data?.spreadSheet}
+ )} From 33c60c5c94ee2313db95be52c1f1c3aff2cefbd3 Mon Sep 17 00:00:00 2001 From: Pratish Ninawe Date: Thu, 28 Sep 2023 16:54:36 +0530 Subject: [PATCH 2/4] integrated assembly api from the backend to extract text --- package.json | 2 + src/_nav.js | 120 +++++++----- src/components/AppHeader.js | 62 +++--- src/components/AppSidebarNav.js | 50 +++-- src/views/Campaigns/AddCampaign.js | 62 +++--- src/views/Campaigns/BasicDetaiils.js | 57 +++--- src/views/Campaigns/Campaign.js | 99 +++++----- src/views/Campaigns/ContactDetails.js | 76 +++----- src/views/Campaigns/Preview.js | 122 +++++++++--- src/views/Campaigns/TestLaunch.js | 80 +++++++- src/views/Campaigns/VideoTemplate.js | 263 ++++++++++++++++++++------ 11 files changed, 632 insertions(+), 361 deletions(-) diff --git a/package.json b/package.json index 095caf2..ca3b201 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "react-date-picker": "^8.4.0", "react-datepicker": "^4.8.0", "react-dom": "^18.0.0", + "react-dropzone": "^14.2.3", "react-hot-toast": "^2.4.0", "react-multistep": "^5.5.8", "react-paginate": "^8.1.3", @@ -71,6 +72,7 @@ "redux": "4.1.2", "serve": "^13.0.2", "simplebar-react": "^2.3.6", + "styled-components": "^6.0.8", "sweetalert": "^2.1.2", "sweetalert2": "^11.4.0", "webpack": "4.44.2", diff --git a/src/_nav.js b/src/_nav.js index f9c5d44..53c8975 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -36,8 +36,7 @@ import { cilTags, cilTennisBall, cilText, - cilUser - , + cilUser, } from "@coreui/icons"; import { CNavGroup, CNavItem, CNavTitle } from "@coreui/react"; @@ -48,55 +47,33 @@ const _nav = [ to: "/dashboard", icon: , }, - { component: CNavItem, - name: "Products", - icon: , - to: "/products", + name: "Campaigns", + icon: , + to: "/campaigns", }, - // { - // component: CNavItem, - // name: 'Departures', - // icon: , - // to: '/departures', - // }, - { - component: CNavItem, - name: "Testimonials", - icon: , - to: "/testimonials", - }, - { - component: CNavItem, - name: "Contact Requests", - icon: , - to: "/contact/request", - }, - - // { - // component: CNavItem, - // name: 'Information', - // icon: , - // to: '/informations', - // }, - - { - component: CNavItem, - name: "Appointments", - icon: , - to: "/appointments", - }, - { component: CNavItem, name: "Users", icon: , to: "/users", }, + { + component: CNavItem, + name: "Recipients", + icon: , + to: "/recipents", + }, + { + component: CNavItem, + name: "Products", + icon: , + to: "/products", + }, { component: CNavGroup, - name: "Franchisee Orders", + name: "Orders", icon: , items: [ { @@ -137,19 +114,24 @@ const _nav = [ }, ], }, - { - component: CNavItem, - name: "Recipients", - icon: , - to: "/recipents", - }, - { - component: CNavItem, - name: "Campaigns", - icon: , - to: "/campaigns", + component: CNavGroup, + name: "Website Related", + icon: , + items: [ + { + component: CNavItem, + name: "Testimonials", + icon: , + to: "/testimonials", + }, + { + component: CNavItem, + name: "Contact Requests", + icon: , + to: "/contact/request", + }, + ], }, { component: CNavGroup, @@ -244,6 +226,40 @@ const _nav = [ }, ], }, + + // { + // component: CNavItem, + // name: 'Departures', + // icon: , + // to: '/departures', + // }, + + // { + // component: CNavItem, + // name: "Testimonials", + // icon: , + // to: "/testimonials", + // }, + // { + // component: CNavItem, + // name: "Contact Requests", + // icon: , + // to: "/contact/request", + // }, + + // { + // component: CNavItem, + // name: 'Information', + // icon: , + // to: '/informations', + // }, + + // { + // component: CNavItem, + // name: "Appointments", + // icon: , + // to: "/appointments", + // }, ]; export default _nav; diff --git a/src/components/AppHeader.js b/src/components/AppHeader.js index 7ad2c6e..d269634 100644 --- a/src/components/AppHeader.js +++ b/src/components/AppHeader.js @@ -1,6 +1,6 @@ -import React from 'react' -import { NavLink } from 'react-router-dom' -import { useSelector, useDispatch } from 'react-redux' +import React from "react"; +import { NavLink } from "react-router-dom"; +import { useSelector, useDispatch } from "react-redux"; import { CContainer, CHeader, @@ -10,24 +10,23 @@ import { CHeaderToggler, CNavLink, CNavItem, -} from '@coreui/react' -import CIcon from '@coreui/icons-react' -import { cilBell, cilEnvelopeOpen, cilList, cilMenu } from '@coreui/icons' +} from "@coreui/react"; +import CIcon from "@coreui/icons-react"; +import { cilBell, cilEnvelopeOpen, cilList, cilMenu } from "@coreui/icons"; -import { AppBreadcrumb } from './index' -import { AppHeaderDropdown } from './header/index' -import { logo } from 'src/assets/brand/logo' -import axios from 'axios' -import { useEffect } from 'react' -import { useState } from 'react' -import { isAutheticated } from 'src/auth' +import { AppBreadcrumb } from "./index"; +import { AppHeaderDropdown } from "./header/index"; +import { logo } from "src/assets/brand/logo"; +import axios from "axios"; +import { useEffect } from "react"; +import { useState } from "react"; +import { isAutheticated } from "src/auth"; const AppHeader = () => { - const dispatch = useDispatch() - const sidebarShow = useSelector((state) => state.sidebarShow) - const [AppName, setAppName] = useState('') - const token = isAutheticated() - + const dispatch = useDispatch(); + const sidebarShow = useSelector((state) => state.sidebarShow); + const [AppName, setAppName] = useState(""); + const token = isAutheticated(); useEffect(() => { async function getConfiguration() { @@ -35,18 +34,17 @@ const AppHeader = () => { headers: { Authorization: `Bearer ${token}`, }, - }) - setAppName(configDetails.data.result[0]?.appName) - + }); + setAppName(configDetails.data.result[0]?.appName); } - getConfiguration() - }, []) + getConfiguration(); + }, []); return ( dispatch({ type: 'set', sidebarShow: !sidebarShow })} + onClick={() => dispatch({ type: "set", sidebarShow: !sidebarShow })} > @@ -55,7 +53,11 @@ const AppHeader = () => { - +

{AppName}

@@ -88,11 +90,9 @@ const AppHeader = () => {
- - {/* */} - + {/* */}
- ) -} + ); +}; -export default AppHeader +export default AppHeader; diff --git a/src/components/AppSidebarNav.js b/src/components/AppSidebarNav.js index 3841783..fd3092e 100644 --- a/src/components/AppSidebarNav.js +++ b/src/components/AppSidebarNav.js @@ -1,11 +1,11 @@ -import React from 'react' -import { NavLink, useLocation } from 'react-router-dom' -import PropTypes from 'prop-types' +import React from "react"; +import { NavLink, useLocation } from "react-router-dom"; +import PropTypes from "prop-types"; -import { CBadge } from '@coreui/react' +import { CBadge } from "@coreui/react"; export const AppSidebarNav = ({ items }) => { - const location = useLocation() + const location = useLocation(); const navLink = (name, icon, badge) => { return ( <> @@ -16,34 +16,32 @@ export const AppSidebarNav = ({ items }) => { {badge.text} )} - - ) - } + ); + }; const navItem = (item, index) => { - const { component, name, badge, icon, ...rest } = item - const Component = component + const { component, name, badge, icon, ...rest } = item; + const Component = component; return ( <> - {navLink(name, icon, badge)} - ) - } + ); + }; const navGroup = (item, index) => { - const { component, name, icon, to, ...rest } = item - const Component = component + const { component, name, icon, to, ...rest } = item; + const Component = component; return ( { {...rest} > {item.items?.map((item, index) => - - item.items ? navGroup(item, index) : navItem(item, index), + item.items ? navGroup(item, index) : navItem(item, index) )} - ) - } + ); + }; return ( {items && items.map((item, index) => - (item.items ? navGroup(item, index) : navItem(item, index)))} + item.items ? navGroup(item, index) : navItem(item, index) + )} - ) -} + ); +}; AppSidebarNav.propTypes = { items: PropTypes.arrayOf(PropTypes.any).isRequired, -} +}; diff --git a/src/views/Campaigns/AddCampaign.js b/src/views/Campaigns/AddCampaign.js index 8b517b2..bc99feb 100644 --- a/src/views/Campaigns/AddCampaign.js +++ b/src/views/Campaigns/AddCampaign.js @@ -43,7 +43,7 @@ const AddCampaign = () => { video: null, spreadSheet: null, videos: [null, null], - recipients: [{ name: "", phoneNumber: "", email: "" }], + recipients: [{ name: "", contact: "" }], testRecipents: [ { name: "", @@ -169,9 +169,9 @@ const AddCampaign = () => {
Add Campaign
-
+ {/*
- {/* */} +
-
+
*/}
@@ -222,7 +222,9 @@ const AddCampaign = () => { /> )} - {viewState === 2 && } + {viewState === 2 && ( + + )} {viewState === 3 && ( )} @@ -303,7 +305,7 @@ const AddCampaign = () => {
-
handleVideoUpload(e)} + id="campaignName" + value={data?.campaignName} + maxLength="50" + onChange={(e) => handleChange(e)} />
+
+ + +
diff --git a/src/views/Campaigns/Campaign.js b/src/views/Campaigns/Campaign.js index 99d6222..6a326e7 100644 --- a/src/views/Campaigns/Campaign.js +++ b/src/views/Campaigns/Campaign.js @@ -10,27 +10,28 @@ const Campaign = () => { const token = isAutheticated(); const [loading, setLoading] = useState(true); const [success, setSuccess] = useState(true); - const [BusinessesData, setBusinessesData] = useState([]); + const [campaignData, setCampaignData] = useState([]); const [currentPage, setCurrentPage] = useState(1); const [itemPerPage, setItemPerPage] = useState(10); - const [showData, setShowData] = useState(BusinessesData); + const [showData, setShowData] = useState(campaignData); const handleShowEntries = (e) => { setCurrentPage(1); setItemPerPage(e.target.value); }; - const getbusinesses = () => { + const getCampaign = () => { axios - .get(`/api/businesses/getall`, { + .get(`/api/campaign/getAll`, { headers: { "Access-Control-Allow-Origin": "*", Authorization: `Bearer ${token}`, }, }) .then((res) => { - setBusinessesData(res.data?.businesses); + setCampaignData(res.data?.campaigns); + // console.log(res.data?.campaigns); setLoading(false); }) .catch((err) => { @@ -40,17 +41,17 @@ const Campaign = () => { }; useEffect(() => { - getbusinesses(); + getCampaign(); }, [success]); useEffect(() => { const loadData = () => { const indexOfLastPost = currentPage * itemPerPage; const indexOfFirstPost = indexOfLastPost - itemPerPage; - setShowData(BusinessesData.slice(indexOfFirstPost, indexOfLastPost)); + setShowData(campaignData.slice(indexOfFirstPost, indexOfLastPost)); }; loadData(); - }, [currentPage, itemPerPage, BusinessesData]); + }, [currentPage, itemPerPage, campaignData]); // const handleVarification = (id) => { // swal({ @@ -89,36 +90,36 @@ const Campaign = () => { // }) // } const handleDelete = (id) => { - swal({ - title: "Are you sure?", - icon: "error", - buttons: { - Yes: { text: "Yes", value: true }, - Cancel: { text: "Cancel", value: "cancel" }, - }, - }).then((value) => { - if (value === true) { - axios - .delete(`/api/businesses/delete/${id}`, { - headers: { - "Access-Control-Allow-Origin": "*", - Authorization: `Bearer ${token}`, - }, - }) - .then((res) => { - setSuccess((prev) => !prev); - }) - .catch((err) => { - swal({ - title: "Warning", - text: "Something went wrong!", - icon: "error", - button: "Retry", - dangerMode: true, - }); - }); - } - }); + // swal({ + // title: "Are you sure?", + // icon: "error", + // buttons: { + // Yes: { text: "Yes", value: true }, + // Cancel: { text: "Cancel", value: "cancel" }, + // }, + // }).then((value) => { + // if (value === true) { + // axios + // .delete(`/api/businesses/delete/${id}`, { + // headers: { + // "Access-Control-Allow-Origin": "*", + // Authorization: `Bearer ${token}`, + // }, + // }) + // .then((res) => { + // setSuccess((prev) => !prev); + // }) + // .catch((err) => { + // swal({ + // title: "Warning", + // text: "Something went wrong!", + // icon: "error", + // button: "Retry", + // dangerMode: true, + // }); + // }); + // } + // }); }; const formatDate = (inputDate) => { @@ -203,9 +204,9 @@ const Campaign = () => { style={{ background: "rgb(140, 213, 213)" }} > - User Name + Campaign Name {/* Logo */} - Type + Campaign Type Recipients {/* Status */} Action @@ -231,9 +232,7 @@ const Campaign = () => { showData.map((i, idx) => { return ( - - {i.userName ? i.userName : i.business} - + {i.campaignName} {/* {i.banner && i.banner ? No Image @@ -241,9 +240,7 @@ const Campaign = () => {

No image!

} */} - - {i.userType ? i.userType : i.short_url} - + {i.campaignType} {formatDate(i.createdAt)} @@ -284,7 +281,7 @@ const Campaign = () => { - +
@@ -384,7 +381,7 @@ const Campaign = () => { {!( (currentPage + 1) * itemPerPage - itemPerPage > - BusinessesData.length - 1 + campaignData.length - 1 ) && (
  • { className={ !( (currentPage + 1) * itemPerPage - itemPerPage > - BusinessesData.length - 1 + campaignData.length - 1 ) ? "paginate_button page-item next" : "paginate_button page-item next disabled" diff --git a/src/views/Campaigns/ContactDetails.js b/src/views/Campaigns/ContactDetails.js index 11d1657..3a741ed 100644 --- a/src/views/Campaigns/ContactDetails.js +++ b/src/views/Campaigns/ContactDetails.js @@ -8,15 +8,13 @@ const ContactDetails = ({ props }) => { const { data, setData, handleView } = props; const [dataEntryMethod, setDataEntryMethod] = useState("manual"); const [csvData, setCsvData] = useState([]); - // const [recipients, setRecipients] = useState([{ name: "", phoneNumber: "" }]); - // console.log("data", data); const addRecord = () => { setData((prevData) => ({ ...prevData, recipients: [ ...prevData.recipients, - { name: "", phoneNumber: "", email: "" }, + { name: "", contact: "" }, // Initialize contact as an empty string ], })); }; @@ -35,14 +33,13 @@ const ContactDetails = ({ props }) => { const row = rows[i].split(","); if (row.length >= 2) { const name = row[0].trim(); - const email = row[1].trim(); - if (name && email) { - extractedData.push({ name, email }); + const contact = row[1].trim(); + if (name && contact) { + extractedData.push({ name, contact }); } } } setCsvData(extractedData); - // console.log(csvData); setData((prevData) => ({ ...prevData, recipients: extractedData, @@ -74,23 +71,11 @@ const ContactDetails = ({ props }) => { })); }; - const recipientNumberChange = (e, index) => { + const recipientContactChange = (e, index) => { const updatedRecipients = [...data.recipients]; updatedRecipients[index] = { ...updatedRecipients[index], - phoneNumber: e.target.value, - }; - setData((prevData) => ({ - ...prevData, - recipients: updatedRecipients, - })); - }; - - const recipientEmailChange = (e, index) => { - const updatedRecipients = [...data.recipients]; - updatedRecipients[index] = { - ...updatedRecipients[index], - email: e.target.value, + contact: e.target.value, }; setData((prevData) => ({ ...prevData, @@ -101,11 +86,7 @@ const ContactDetails = ({ props }) => { const handleSubmit = () => { if ( data?.recipients.every( - (recipient) => - recipient.name !== "" && - (data?.campaignType !== "email" - ? recipient.phoneNumber !== "" - : recipient.email !== "") + (recipient) => recipient.name !== "" && recipient.contact !== "" ) ) { handleView(4); @@ -171,50 +152,41 @@ const ContactDetails = ({ props }) => {
    {data?.recipients.map((recipient, index) => { return ( -
    +
    -
    -
    {index !== 0 && ( diff --git a/src/views/Campaigns/Preview.js b/src/views/Campaigns/Preview.js index 3ff3b77..2aada17 100644 --- a/src/views/Campaigns/Preview.js +++ b/src/views/Campaigns/Preview.js @@ -1,23 +1,83 @@ -import React from "react"; +import React, { useState } from "react"; import Button from "@material-ui/core/Button"; +import axios from "axios"; +import { isAutheticated } from "src/auth"; + const Preview = ({ props }) => { + const token = isAutheticated(); const { data, handleView, setData } = props; - console.log(data); + const [loading, setLoading] = useState(false); + + const handleSubmit = async (e) => { + e.preventDefault(); + // console.log(data); + + // const campaignData = { + // campaignType: data.campaignType, + // campaignName: data.campaignName, + // language: data.language, + // videoTemplate: data.video, + // recipients: data.recipients, + // }; + + const formattedRecipients = data.recipients.map((recipient) => ({ + name: recipient.name, + contact: recipient.contact.email || recipient.contact.phoneNumber, + })); + // console.log(data.campaignType); + + const formData = new FormData(); + formData.append("campaignType", data.campaignType); + formData.append("campaignName", data.campaignName); + formData.append("language", data.language); + formData.append("videoTemplate", data.video); + // formData.set("recipients",JSON.stringify(formattedRecipients)); + // console.log("campaignData", campaignData); + // console.log("formData", formData); + + axios + .post(`/api/campaign/create`, formData, { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "multipart/form-data", + "Access-Control-Allow-Origin": "*", + }, + }) + .then((res) => { + // console.log(res); + swal({ + title: "Added", + text: res?.data?.message + ? res?.data?.message + : "Campaign added successfully!", + icon: "success", + button: "Return", + }); + setLoading(false); + // handleView(5); + }) + .catch((err) => { + setLoading(false); + const message = err.response?.data?.message || "Something went wrong!"; + // console.log(message); + swal({ + title: "Warning", + text: message, + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + }; + + // console.log(data); return ( -
    +
    -
    +
    Campaign Details
    -
    )} -
    +
    + +
    + ); }; diff --git a/src/views/Campaigns/TestLaunch.js b/src/views/Campaigns/TestLaunch.js index 31b10ea..13271e3 100644 --- a/src/views/Campaigns/TestLaunch.js +++ b/src/views/Campaigns/TestLaunch.js @@ -3,6 +3,14 @@ import Button from "@material-ui/core/Button"; import { useState } from "react"; import toast from "react-hot-toast"; import { CFormInput, CFormLabel, CCol, CRow } from "@coreui/react"; +import { + CButton, + CTable, + CTableBody, + CTableDataCell, + CTableHead, + CTableRow, +} from "@coreui/react"; const TestLaunch = ({ props }) => { const { data, setData, handleView } = props; @@ -112,7 +120,7 @@ const TestLaunch = ({ props }) => {
    -
    + {/*
    @@ -201,7 +209,75 @@ const TestLaunch = ({ props }) => {
    -
    +
    */} + {data && ( +
    + + + + Video + Name + Contact + + + + {/* {renderTableRows()} */} + + + + + + test + test@gmail.com + + Send + + + + + + + test + test@gmail.com + + Send + + + + + + + test + test@gmail.com + + Send + + + + +
    + )}
    ); }; diff --git a/src/views/Campaigns/VideoTemplate.js b/src/views/Campaigns/VideoTemplate.js index 10dd6db..d78c4ca 100644 --- a/src/views/Campaigns/VideoTemplate.js +++ b/src/views/Campaigns/VideoTemplate.js @@ -1,19 +1,176 @@ import React, { useState } from "react"; import Button from "@material-ui/core/Button"; +import styled from "styled-components"; +import axios from "axios"; +import { isAutheticated } from "src/auth"; -const VideoTemplate = () => { +const GridContainer = styled.div` + display: grid; + grid-template-columns: auto auto; + grid-gap: 0px; +`; + +const GridItem = styled.div` + display: grid; + font-size: 20px; + text-align: center; +`; + +const UploadContainer = styled.div` + width: 100%; + border: 1.5px dashed gray; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; +`; + +const UploadButton = styled.button` + margin-top: 20px; + border: none; + font-size: 15px; + padding: 10px; +`; + +const VideoPreview = styled.video` + width: 100%; + height: 20rem; + margin-top: 50px; +`; + +const DeleteButton = styled.button` + position: absolute; + top: 10px; + right: 10px; + background: transparent; + border: none; +`; + +const VideoTemplate = ({ props }) => { + const token = isAutheticated(); + const { data, setData, handleView } = props; const [selectedFile, setSelectedFile] = useState(null); + const [isLoading, setIsLoading] = useState(false); + const [transcribedText, setTranscribedText] = useState(""); - const handleFileChange = (e) => { + const handleVideoUpload = async (e) => { const file = e.target.files[0]; if (file) { - setSelectedFile(URL.createObjectURL(file)); + setData((prev) => ({ + ...prev, + [e.target.id]: file, + })); + } + + setSelectedFile(URL.createObjectURL(file)); + + setIsLoading(true); + try { + const formData = new FormData(); + // console.log(data.video); + formData.append("videoTemplate", data.video); + + const response = await axios.post("/api/campaign/convert", formData, { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "multipart/form-data", + "Access-Control-Allow-Origin": "*", + }, + }); + + const { success, message, text } = response.data; + if (success) { + setTranscribedText(text); + setIsLoading(false); + swal({ + title: "Converted", + text: "Text Extracted Successfully", + icon: "success", + button: "Close", + }); + } else { + swal({ + title: "API Error", + text: message, + icon: "error", + button: "Close", + }); + setIsLoading(false); + console.log("API Error:", message); + } + } catch (error) { + swal({ + title: "Network Error", + text: error.message, + icon: "error", + button: "Close", + }); + setIsLoading(false); + console.log("Network Error:", error.message); } }; const handleDelete = () => { setSelectedFile(null); - // You can also perform additional actions here, such as clearing the file input field. + }; + + const extractText = async (e) => { + e.preventDefault(); + + if (data.video === null) { + swal({ + title: "Error", + text: "Please upload video", + icon: "error", + button: "Close", + }); + return; + } + setIsLoading(true); + try { + const formData = new FormData(); + // console.log(data.video); + formData.append("videoTemplate", data.video); + + const response = await axios.post("/api/campaign/convert", formData, { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "multipart/form-data", + "Access-Control-Allow-Origin": "*", + }, + }); + + const { success, message, text } = response.data; + if (success) { + setTranscribedText(text); + setIsLoading(false); + swal({ + title: "Converted", + text: "Text Extracted Successfully", + icon: "success", + button: "Close", + }); + } else { + swal({ + title: "API Error", + text: message, + icon: "error", + button: "Close", + }); + setIsLoading(false); + console.log("API Error:", message); + } + } catch (error) { + swal({ + title: "Network Error", + text: error.message, + icon: "error", + button: "Close", + }); + setIsLoading(false); + console.log("Network Error:", error.message); + } }; return ( @@ -22,7 +179,7 @@ const VideoTemplate = () => {
    - Upload Video + Upload Video to Create Template

    @@ -39,7 +196,7 @@ const VideoTemplate = () => { marginRight: "5px", }} onClick={() => { - handeView(1); + handleView(1); }} > Prev @@ -53,7 +210,7 @@ const VideoTemplate = () => { textTransform: "capitalize", }} onClick={() => { - handeView(3); + handleView(3); }} > Next @@ -64,55 +221,51 @@ const VideoTemplate = () => {
    -
    -
    -
    - -
    - -
    -
    - {selectedFile && ( -
    -
    - {/* Add spacing text on the left */} -

    This is some text with spacing

    -
    -
    - - × - - -
    -
    - )} -
    -
    + + × + + ) : ( + + + + document.getElementById("video").click()} + > + SELECT FILES + + + )} + + +
    From 7794ada908d06af0463b0ec85e22b10cf8bddf19 Mon Sep 17 00:00:00 2001 From: Pratish Ninawe Date: Fri, 29 Sep 2023 15:55:27 +0530 Subject: [PATCH 3/4] integrated api for tab 3 contact details --- src/views/Campaigns/ContactDetails.js | 4 +- src/views/Campaigns/Preview.js | 65 +++++++++++---------------- 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/src/views/Campaigns/ContactDetails.js b/src/views/Campaigns/ContactDetails.js index 3a741ed..99c899c 100644 --- a/src/views/Campaigns/ContactDetails.js +++ b/src/views/Campaigns/ContactDetails.js @@ -180,7 +180,9 @@ const ContactDetails = ({ props }) => { { const handleSubmit = async (e) => { e.preventDefault(); - // console.log(data); - // const campaignData = { - // campaignType: data.campaignType, - // campaignName: data.campaignName, - // language: data.language, - // videoTemplate: data.video, - // recipients: data.recipients, - // }; + const hasEmptyRecipients = data.recipients.some((recipient) => { + return !recipient.name || !recipient.contact; + }); + + if (hasEmptyRecipients) { + swal({ + title: "Validation Error", + text: "Please fill Conatct details", + icon: "error", + button: "Close", + }); + return; + } const formattedRecipients = data.recipients.map((recipient) => ({ name: recipient.name, - contact: recipient.contact.email || recipient.contact.phoneNumber, + contact: recipient.contact, })); - // console.log(data.campaignType); - const formData = new FormData(); - formData.append("campaignType", data.campaignType); - formData.append("campaignName", data.campaignName); - formData.append("language", data.language); - formData.append("videoTemplate", data.video); - // formData.set("recipients",JSON.stringify(formattedRecipients)); - // console.log("campaignData", campaignData); - // console.log("formData", formData); + const campaignData = { + campaignType: data.campaignType, + campaignName: data.campaignName, + language: data.language, + recipients: formattedRecipients, + }; axios - .post(`/api/campaign/create`, formData, { + .post(`/api/campaign/create`, campaignData, { headers: { Authorization: `Bearer ${token}`, - "Content-Type": "multipart/form-data", "Access-Control-Allow-Origin": "*", }, }) @@ -51,10 +52,10 @@ const Preview = ({ props }) => { ? res?.data?.message : "Campaign added successfully!", icon: "success", - button: "Return", + button: "Close", }); setLoading(false); - // handleView(5); + handleView(5); }) .catch((err) => { setLoading(false); @@ -64,7 +65,7 @@ const Preview = ({ props }) => { title: "Warning", text: message, icon: "error", - button: "Retry", + button: "Close", dangerMode: true, }); }); @@ -100,9 +101,7 @@ const Preview = ({ props }) => { marginBottom: "1rem", textTransform: "capitalize", }} - onClick={() => { - handleView(5); - }} + onClick={handleSubmit} > Next @@ -147,20 +146,6 @@ const Preview = ({ props }) => {
    )} -
    - -
    ); }; From 2238dc074d5ba814b3df985188800cad05bbc7c8 Mon Sep 17 00:00:00 2001 From: Pratish Ninawe Date: Tue, 3 Oct 2023 10:13:34 +0530 Subject: [PATCH 4/4] worked on preview files --- src/views/Campaigns/ContactDetails.js | 69 +++++++++++++++++++----- src/views/Campaigns/Preview.js | 75 +++++++++------------------ src/views/Campaigns/Video.js | 4 +- 3 files changed, 81 insertions(+), 67 deletions(-) diff --git a/src/views/Campaigns/ContactDetails.js b/src/views/Campaigns/ContactDetails.js index 99c899c..3844e12 100644 --- a/src/views/Campaigns/ContactDetails.js +++ b/src/views/Campaigns/ContactDetails.js @@ -3,8 +3,11 @@ import Button from "@material-ui/core/Button"; import { useState } from "react"; import toast from "react-hot-toast"; import { CFormInput, CFormLabel, CCol, CRow } from "@coreui/react"; +import axios from "axios"; +import { isAutheticated } from "src/auth"; const ContactDetails = ({ props }) => { + const token = isAutheticated(); const { data, setData, handleView } = props; const [dataEntryMethod, setDataEntryMethod] = useState("manual"); const [csvData, setCsvData] = useState([]); @@ -12,10 +15,7 @@ const ContactDetails = ({ props }) => { const addRecord = () => { setData((prevData) => ({ ...prevData, - recipients: [ - ...prevData.recipients, - { name: "", contact: "" }, // Initialize contact as an empty string - ], + recipients: [...prevData.recipients, { name: "", contact: "" }], })); }; @@ -83,16 +83,59 @@ const ContactDetails = ({ props }) => { })); }; - const handleSubmit = () => { - if ( - data?.recipients.every( - (recipient) => recipient.name !== "" && recipient.contact !== "" - ) - ) { - handleView(4); - } else { - toast.error("Fill all contact details"); + const handleSubmit = (e) => { + e.preventDefault(); + + const hasEmptyRecipients = data.recipients.some((recipient) => { + return !recipient.name || !recipient.contact; + }); + + if (hasEmptyRecipients) { + toast.error("Please fill Conatct details"); + return; } + + const formattedRecipients = data.recipients.map((recipient) => ({ + name: recipient.name, + contact: recipient.contact, + })); + + const campaignData = { + campaignType: data.campaignType, + campaignName: data.campaignName, + language: data.language, + recipients: formattedRecipients, + }; + + axios + .post(`/api/campaign/create`, campaignData, { + headers: { + Authorization: `Bearer ${token}`, + "Access-Control-Allow-Origin": "*", + }, + }) + .then((res) => { + // console.log(res); + handleView(4); + toast.success("Campaign added successfully!"); + setLoading(false); + }) + .catch((err) => { + setLoading(false); + const message = err.response?.data?.message || "Something went wrong!"; + // console.log(message); + toast.error(message); + }); + + // if ( + // data?.recipients.every( + // (recipient) => recipient.name !== "" && recipient.contact !== "" + // ) + // ) { + // handleView(4); + // } else { + // toast.error("Fill all contact details"); + // } }; return ( diff --git a/src/views/Campaigns/Preview.js b/src/views/Campaigns/Preview.js index b29c5c2..bde6986 100644 --- a/src/views/Campaigns/Preview.js +++ b/src/views/Campaigns/Preview.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import Button from "@material-ui/core/Button"; import axios from "axios"; import { isAutheticated } from "src/auth"; @@ -7,71 +7,44 @@ const Preview = ({ props }) => { const token = isAutheticated(); const { data, handleView, setData } = props; const [loading, setLoading] = useState(false); + const [campaignData, setCampaignData] = useState([]); const handleSubmit = async (e) => { e.preventDefault(); - const hasEmptyRecipients = data.recipients.some((recipient) => { - return !recipient.name || !recipient.contact; - }); - - if (hasEmptyRecipients) { - swal({ - title: "Validation Error", - text: "Please fill Conatct details", - icon: "error", - button: "Close", - }); - return; + if ( + data?.recipients.every( + (recipient) => recipient.name !== "" && recipient.contact !== "" + ) + ) { + handleView(4); + } else { + toast.error("Fill all contact details"); } + }; - const formattedRecipients = data.recipients.map((recipient) => ({ - name: recipient.name, - contact: recipient.contact, - })); - - const campaignData = { - campaignType: data.campaignType, - campaignName: data.campaignName, - language: data.language, - recipients: formattedRecipients, - }; - + const getCampaign = () => { axios - .post(`/api/campaign/create`, campaignData, { + .get(`/api/campaign/getAll`, { headers: { - Authorization: `Bearer ${token}`, "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, }, }) .then((res) => { - // console.log(res); - swal({ - title: "Added", - text: res?.data?.message - ? res?.data?.message - : "Campaign added successfully!", - icon: "success", - button: "Close", - }); + setCampaignData(res.data?.campaigns); setLoading(false); - handleView(5); }) .catch((err) => { + console.log(err); setLoading(false); - const message = err.response?.data?.message || "Something went wrong!"; - // console.log(message); - swal({ - title: "Warning", - text: message, - icon: "error", - button: "Close", - dangerMode: true, - }); }); }; - // console.log(data); + useEffect(() => { + getCampaign(); + }, []); + return (
    @@ -115,16 +88,16 @@ const Preview = ({ props }) => { Campaign Name - {data?.campaignName} + {campaignData.campaignName} Language - {data?.language} + {campaignData.language} Campaign Type - {data?.campaignType} + {campaignData.campaignType} Video @@ -140,7 +113,7 @@ const Preview = ({ props }) => { Recipients - {data?.recipients?.length} + {campaignData.recipients} diff --git a/src/views/Campaigns/Video.js b/src/views/Campaigns/Video.js index 6edb1e6..3a54c59 100644 --- a/src/views/Campaigns/Video.js +++ b/src/views/Campaigns/Video.js @@ -23,7 +23,6 @@ const Video = ({ props }) => { const deleteRecord = (index) => { if (index >= 2) { - // Only allow deletion for videos starting from the third one setData((prev) => ({ ...prev, videos: prev.videos.filter((_, i) => i !== index), @@ -31,7 +30,6 @@ const Video = ({ props }) => { } }; - console.log(data); return (
    @@ -106,7 +104,7 @@ const Video = ({ props }) => { id={`videoTitle${index + 1}`} onChange={(e) => handleVideoUpload(e, index)} /> - {index >= 2 && ( // Render delete button for videos starting from the third one + {index >= 2 && (