Untitled

 avatar
unknown
plain_text
5 months ago
22 kB
2
Indexable
import { Badge, Box, Button, Flex, FormControl, FormLabel, HStack, Input, Popover, PopoverArrow, PopoverBody, PopoverContent, PopoverTrigger, Select, Spinner, Table, TableContainer, Tag, Tbody, Td, Text, Th, Thead, Tr, useDisclosure } from "@chakra-ui/react";
import { compact, filter, join, map, omit, size } from "lodash";
import { useRouter } from "next/router";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { AiOutlineLeft, AiOutlineRight } from "react-icons/ai";
import { CustomContainer } from "../../components/CustomContainer";
import { STATUS } from "../../constants";
import { useStudenStore } from "../../store/StudentsStore";
import { useLeadsStore } from "../../store/LeadsStore";
import { InfoIcon } from "@chakra-ui/icons";
import dayjs from "dayjs";
import { ConsumeModal } from "./ConsumeModal";
import { UploadLeadsModal } from "./UploadLeadModal";
import { ManageLeadsCall } from "./ManageLeadsCall";
import { EmptyPage } from "../../utils/EmptyPage";

const pagePerLimits = [10, 20, 30, 40, 50];

export const AllLeads = ({ leadListId, getOneLeadList }) => {
    const router = useRouter()
    const { control, handleSubmit, getValues, reset, setValue, watch } = useForm()
    const { isOpen, onOpen, onClose } = useDisclosure()
    const { isOpen: manageLeadIsOpen, onOpen: manageLeadOnOpen, onClose: manageLeadOnClose } = useDisclosure()

    const { getAllLeadsAction, getAllLeadsStatus, allLeads } = useStudenStore(s => ({
        getAllLeadsAction: s.getAllLeadsAction,
        getAllLeadsStatus: s.getAllLeadsStatus,
        allLeads: s.allLeads
    }))
    const { getFbAccountsAction, getFbAccountsStatus, fbAccounts, getFbPagesAction, getFbPagesStatus, fbPagesList, getAllActiveFormsAction, getAllActiveFormsStatus, allActiveForms, } = useLeadsStore(s => ({
        getFbAccountsAction: s.getFbAccountsAction,
        getFbAccountsStatus: s.getFbAccountsStatus,
        fbAccounts: s.fbAccounts,
        getFbPagesAction: s.getFbPagesAction,
        getFbPagesStatus: s.getFbPagesStatus,
        fbPagesList: s.fbPagesList,
        getAllActiveFormsAction: s.getAllActiveFormsAction,
        getAllActiveFormsStatus: s.getAllActiveFormsStatus,
        allActiveForms: s.allActiveForms,
    }))

    useEffect(() => {
        getFbAccountsAction()
        getFbPagesAction()
    }, [getFbAccountsAction, getFbPagesAction])

    const selectedPage = watch("pageId")
    useEffect(() => {
        if (selectedPage) {
            getAllActiveFormsAction({ pageId: selectedPage })
        }
    }, [getAllActiveFormsAction, selectedPage])

    const [curPage, setCurPage] = useState(1);
    const [pagePerLimit, setPagePerLimit] = useState(10);

    const getData = useCallback((data) => {
        let payload = { page: curPage, limit: pagePerLimit, ...data }
        if (leadListId) { payload.leadListId = leadListId }
        getAllLeadsAction(payload)
    }, [getAllLeadsAction, curPage, pagePerLimit, leadListId])

    const hasNextPage = useMemo(
        () => parseInt(allLeads?.page) != allLeads?.totalPages,
        [allLeads],
    );
    const hasPrevPage = useMemo(
        () => parseInt(allLeads?.page) != 1,
        [allLeads],
    );

    useEffect(() => {
        getData()
    }, [getData])

    const goToNextPage = () => {
        if (hasNextPage)
            setCurPage(pre => pre + 1)
    }

    const goToPrevPage = () => {
        if (hasPrevPage)
            setCurPage(pre => pre - 1)
    }

    const _submit = (d) => {
        const payload = { page: curPage, limit: pagePerLimit }
        if (d.name) { payload.name = d.name }
        if (d.source) { payload.leadSource = d.source }
        if (d.formId) { payload.facebookFormId = d.formId }
        if (d.pageId) { payload.facebookPageId = d.pageId }

        if (curPage === 1)
            getData()
        else
            setCurPage(1)
    }

    const _reset = () => {
        setValue("source", "")
        setValue("name", "")
        if (curPage === 1)
            getData({ page: curPage, limit: pagePerLimit })
        else
            setCurPage(1)
    }

    const handlePageLimitChange = (e) => {
        setCurPage(1);
        setPagePerLimit(e.target.value)
    }

    const selectedSource = watch("source")
    const selectedAccount = watch("accountId")
    useEffect(() => {
        setValue("accountId", "")
        setValue("pageId", "")
        setValue("formId", "")
    }, [selectedSource, setValue])

    useEffect(() => {
        setValue("pageId", "")
        setValue("formId", "")
    }, [selectedAccount, setValue])

    useEffect(() => {
        setValue("formId", "")
    }, [selectedPage, setValue])

    const [toggleConsumeModal, setToggleConsumeModal] = useState(null)

    const consumeAction = (id) => {
        setToggleConsumeModal(id)
    }

    const manageLeadsCallHandler = () => {
        manageLeadOnOpen()
    }

    const goToProfile = (user) => {
        if (user?._id) {
            router.push(`/leads/${user._id}`);
        }
    }

    return (
        <CustomContainer heading={leadListId ? getOneLeadList?.name : "All Leads"} isBackButton={true} >
            <Box>
                <Flex justifyContent={"space-between"} >
                    <Box>
                        <form onSubmit={handleSubmit(_submit)}>
                            <HStack align={"end"} mb={2}>

                                <FormControl w="fit-content">
                                    <FormLabel>Name</FormLabel>
                                    <Controller
                                        name="name"
                                        control={control}
                                        render={({ field }) => (
                                            <Input placeholder="Enter Name" {...field} type="text" size={'sm'} />
                                        )}
                                    />
                                </FormControl>

                                <FormControl w="fit-content">
                                    <FormLabel>Source</FormLabel>
                                    <Controller
                                        name="source"
                                        control={control}
                                        render={({ field }) => (
                                            <Select size={'sm'} {...field} placeholder="Select Source" >
                                                <option value="FACEBOOK">FACEBOOK</option>
                                                <option value="WEBSITE">WEBSITE</option>
                                                <option value="OTHER">OTHER</option>
                                            </Select>
                                        )}
                                    />
                                </FormControl>
                                {watch("source") === "FACEBOOK" ?
                                    <>
                                        <FormControl w="fit-content" isRequired={watch("source") === "FACEBOOK"} >
                                            <FormLabel>Account</FormLabel>
                                            <Controller
                                                name="accountId"
                                                control={control}
                                                render={({ field }) => (
                                                    <Select size={'sm'} {...field} placeholder="Select Account">
                                                        {map(fbAccounts, acc => (
                                                            <option value={acc._id}>{acc.name}</option>
                                                        ))}
                                                    </Select>
                                                )}
                                            />
                                        </FormControl>
                                        <FormControl w="fit-content" isRequired={watch("source") === "FACEBOOK"} >
                                            <FormLabel>Page</FormLabel>
                                            <Controller
                                                name="pageId"
                                                control={control}
                                                render={({ field }) => (
                                                    <Select {...field} size={'sm'} placeholder="Select Page">
                                                        {map(filter(fbPagesList, p => p.facebookAccountId === watch("accountId")), acc => (
                                                            <option value={acc.pageId}>{acc.name}</option>
                                                        ))}
                                                    </Select>
                                                )}
                                            />
                                        </FormControl>
                                        <FormControl w="fit-content">
                                            <FormLabel>Ads</FormLabel>
                                            <Controller
                                                name="formId"
                                                control={control}
                                                render={({ field }) => (
                                                    <Select size={'sm'} {...field} placeholder="Select Ads">
                                                        {map(allActiveForms, acc => (
                                                            <option value={acc.formId}>{acc.name}</option>
                                                        ))}
                                                    </Select>
                                                )}
                                            />
                                        </FormControl>
                                    </>
                                    :
                                    null
                                }
                                <HStack>
                                    <Button size="sm" colorScheme="blue" type="submit">Apply</Button>
                                    <Button size="sm" variant={'outline'} onClick={_reset}>Reset</Button>
                                </HStack>
                            </HStack>
                        </form>
                    </Box>
                    {leadListId ? <Box>
                        <Flex>
                            <Button mr={3} size={"sm"} colorScheme="blue" onClick={onOpen}>Upload Leads Excel</Button>
                            <Button size={"sm"} colorScheme="green" onClick={manageLeadsCallHandler}>Manage Leads Call</Button>
                        </Flex>
                    </Box> : null}
                </Flex>

                <Flex pt={3} justify='space-between' bg="white">

                    <Box>
                        <Tag mb={2} px={4} variant='subtle' fontWeight='bold' py={2} colorScheme='blue'>Total Records {allLeads?.totalDocs || 0}</Tag>
                    </Box>
                    <Flex flexGrow={'1'} pl={2} align='center' justify='flex-end' mb={2}>
                        <Box maxW='300px'>
                            <Select onChange={handlePageLimitChange} bg='white' size='sm'>
                                {
                                    map(pagePerLimits, limit => <option key={limit} value={limit}>{limit} Records per page</option>)
                                }
                            </Select>
                        </Box>
                        <Flex ml={8} align='center'>
                            <Box>
                                {allLeads?.page || 0} - {allLeads?.totalPages}
                            </Box>
                            <Flex ml={2} align='center'>
                                <Box onClick={goToPrevPage} cursor='pointer' color={hasPrevPage ? 'gray.700' : 'gray.500'} _hover={hasPrevPage && { color: 'gray.700' }}>
                                    <AiOutlineLeft />
                                </Box>
                                <Box onClick={goToNextPage} cursor='pointer' color={hasNextPage ? 'gray.700' : 'gray.500'} ml={4} _hover={hasNextPage && { color: 'gray.700' }}>
                                    <AiOutlineRight />
                                </Box>
                            </Flex>
                        </Flex>
                    </Flex>
                </Flex>
                <Box>
                    {size(allLeads?.docs) > 0 ?
                        <TableContainer>
                            <Table size={'sm'}>
                                <Thead bg={'gray.100'}>
                                    <Tr>
                                        <Th>Name</Th>
                                        <Th>Father</Th>
                                        <Th>Contact</Th>
                                        <Th>Created At</Th>
                                        <Th>Consume</Th>
                                        <Th></Th>
                                        <Th>Action</Th>
                                    </Tr>
                                </Thead>
                                <Tbody>
                                    {getAllLeadsStatus === STATUS.FETCHING ?
                                        <Tr>
                                            <Td colSpan={6} textAlign='center'>
                                                <Spinner />
                                            </Td>
                                        </Tr>
                                        : allLeads?.docs?.length ?
                                            allLeads.docs.map(user => {
                                                const dataFields = omit(user, "branchId", "leadListId", "createdAt", "facebookFormId", "facebookPageId", "iid", "leadSource", "meta", "updatedAt", "__v", "_id", "name", "father", "contact", "contact1", "consumed", "consumedBy", "consumeRemark", "oldData")
                                                const data = { ...dataFields, ...(dataFields.address ?? {}), ...(dataFields.academicDetails ?? {}) }
                                                return (
                                                    <Tr key={user._id}>
                                                        <Td _hover={{ color: "blue.500" }} onClick={() => goToProfile(user)} cursor={"pointer"} py={0}>
                                                            <Text fontWeight={"semibold"}>{user.name}</Text>
                                                        </Td>
                                                        <Td>
                                                            <Text>{user.father || '-'}</Text>
                                                        </Td>
                                                        <Td w={100}>
                                                            <Text>{join(compact([user.contact, user.contact1]), ', ') || '-'}</Text>
                                                        </Td>
                                                        <Td>{user.createdAt ? dayjs(user.createdAt).format("DD-MM-YYYY") : ''}</Td>
                                                        <Td>
                                                            {user.consumed === true ?
                                                                <Popover trigger="hover">
                                                                    <PopoverTrigger>
                                                                        <Badge cursor="pointer" colorScheme="green" variant="outline">Consumed</Badge>
                                                                    </PopoverTrigger>
                                                                    <PopoverContent bg='black' color='white' whiteSpace={"normal"}>
                                                                        <PopoverArrow bg='black' />
                                                                        <PopoverBody maxW="40vw" h="fit-content">
                                                                            <Box>
                                                                                <Flex mb={2}>
                                                                                    <Text>Consumed By: </Text>
                                                                                    <Text ml={2}>{user.consumedBy?.name}</Text>
                                                                                </Flex>
                                                                                <Text wordBreak="break-word">{user.consumeRemark}</Text>
                                                                            </Box>
                                                                        </PopoverBody>
                                                                    </PopoverContent>
                                                                </Popover>
                                                                :
                                                                <Button size="sm" variant={"outline"} colorScheme="blue" onClick={() => consumeAction(user._id)}>Consume</Button>
                                                            }
                                                        </Td>
                                                        <Td>
                                                            {Object.keys(data)?.length ?
                                                                <Popover trigger="hover" placement={"left"}>
                                                                    <PopoverTrigger>
                                                                        <InfoIcon color="orange.300" />
                                                                    </PopoverTrigger>
                                                                    <PopoverContent>
                                                                        <PopoverArrow />
                                                                        <PopoverBody>
                                                                            <Box>
                                                                                {map(data, (d, key) => {
                                                                                    const word = key.replace(/([A-Z])/g, ' $1');
                                                                                    if (typeof (d) === 'object') { return }
                                                                                    return (
                                                                                        <Flex><strong>{word[0].toUpperCase() + word.substring(1).toLowerCase()} - </strong> &nbsp;&nbsp; {d}</Flex>
                                                                                    )
                                                                                })}
                                                                            </Box>
                                                                        </PopoverBody>
                                                                    </PopoverContent>
                                                                </Popover>
                                                                :
                                                                null
                                                            }
                                                        </Td>
                                                        <Td>
                                                            <Button size="sm" variant={"outline"} colorScheme="blue" onClick={() => router.push("/enquiry/add?id=" + user._id)}>Add Enquiry</Button>
                                                        </Td>
                                                    </Tr>
                                                )
                                            })
                                            :
                                            null
                                    }
                                </Tbody>
                            </Table>
                            {toggleConsumeModal && <ConsumeModal student={toggleConsumeModal} closeModal={() => setToggleConsumeModal(null)} />}
                        </TableContainer>
                        :
                        <EmptyPage height={300} />
                    }
                </Box>
            </Box>
            <UploadLeadsModal isOpen={isOpen} onClose={onClose} leadListId={leadListId} />
            <ManageLeadsCall isOpen={manageLeadIsOpen} onClose={manageLeadOnClose} leadListId={leadListId} getOneLeadList={getOneLeadList} />
        </CustomContainer>
    )
}
Editor is loading...
Leave a Comment