# Lead count over period widget

The **LeadCountOverPeriodWidget** displays the number of **leads** added for each status and the percentage difference between the current period's total and that of the previous equivalent period (e.g., if October is selected, the past period will be September). The component is built using the **Ant Design** **Carousel** and **LeadAmountDifferenceWidget** components.

For correct display of widgets (4 per carousel page) we should chunk our array of data by smaller one's with size of 4. Then we well map chunked arrays and map each array sepaarately to generate widgets. Code example:

<pre class="language-javascript"><code class="lang-javascript"><strong>&#x3C;Carousel infinite={false} draggable className={classes.carousel}>
</strong>                {chunkedLeadAmount.map((chunk, index) => (
                    &#x3C;div key={index} className={classes.chunk}>
                        {chunk.map((item, idx) => (
                            &#x3C;LeadAmountDiffenceWidget
                                key={idx}
                                title={item.name}
                                icon={leadAmountWidgetIcons[item.name]}
                                iconBgColor={item.backgroundColor}
                                sparkLineColor={item.color}
                                leadAmount={item.current}
                                percentageDifference={item.percentageChange}
                            />
                        ))}
                    &#x3C;/div>
                ))}
            &#x3C;/Carousel>
</code></pre>

In **LeadAmountDiffenceWidget** we will display passed information and add a **SparkLine** with correct color and with direction based on `percentageDifference`. Inside **LeadAmountDiffenceWidget**  we create a variable with value of "Ascend"  | "Descend" | "none" called  type:

```javascript
    const type =
        percentageDifference > 0 ? sortTypes.ascent : percentageDifference < 0 ? sortTypes.descent : sortTypes.none;
```

Which we pass to **SparkLine** component

```javascript
<SparkLine type={type} color={sparkLineColor} />
```

Inside the component it will be 3 different svg lines which will returned depends on type. Also each line have linear gradient under it. To achieve correct gradient display we should create an **unique gradient id** in the following way:

```javascript
const gradientId = `gradient_${type}_${color.replace('#', '')}`;
```

You may use also **UUID** or something else for that purpose.

Then use this gradientId in your `svg` tag:

```javascript
            <svg
                style={svgStyle}
                width="134"
                height="64"
                viewBox="0 0 67 32"
                fill="none"
                xmlns="http://www.w3.org/2000/svg"
            >
                <path
                    d="M15.173 20.5956L1 31H66V1L50.8327 9.85036C45.8547 12.7551 40.1946 14.2857 34.4311 14.2857C27.5038 14.2857 20.7572 16.4962 15.173 20.5956Z"
                    fill={`url(#${gradientId})`}
                    fillOpacity="0.3"
                />
                <path
                    d="M1 31L15.173 20.5956C20.7572 16.4962 27.5038 14.2857 34.4311 14.2857V14.2857C40.1946 14.2857 45.8547 12.7551 50.8327 9.85036L66 1"
                    stroke={color}
                    strokeLinecap="round"
                />
                <defs>
                    <linearGradient id={gradientId} x1="33.5" y1="1" x2="33.5" y2="31" gradientUnits="userSpaceOnUse">
                        <stop stopColor={color} />
                        <stop offset="1" stopColor={color} stopOpacity="0" />
                    </linearGradient>
                </defs>
            </svg>
```

As you can see, we need to pass it to the `fill` attribute of the first `path` tag with a URL to ensure the correct color. To apply the gradient under the line correctly, use `linearGradient` with a unique `gradientId`. If `gradientId` is not unique, all lines will appear black and lack gradient.

### Backend

On backend we have `countLeadsOverPeriod` function which return us an array of object for each lead status with following fields:

* name - the name of lead status
* current - total amount of leads with current status
* percentageChange - rounded difference between current and past period in percentage
* color - status primary color
* backgroundColor - status secondary color

To create that array, we first need to retrieve all statuses for the user's `teamId`. Then, we create a query for each status using a **for** loop, which will return the count of leads that were created within the required period and currently have the specified status. Query:

```typescript
const currentQuery = this.leadsRepository
                .createQueryBuilder('lead')
                .leftJoin('lead.business', 'business')
                .leftJoin('lead.status', 'status')
                .where('lead.statusId = :statusId', { statusId })
                .andWhere('lead.teamId = :teamId', { teamId })
                .andWhere('lead.createdAt BETWEEN :startOfDay AND :endOfDay', { startOfDay, endOfDay })
                .andWhere('business.id IN (:...businessesIds)', { businessesIds });
```

To get the lead count for the previous time period (to calculate the percentage difference), we will run almost the same query but with a different `startOfDay` and `endOfDay`. After that, we calculate the percentage difference and push an object with the required values into the resulting array. Here is the full code of the complete cycle:

```typescript
for (const status of statuses) {
            const statusId = status.id;

            const currentQuery = this.leadsRepository
                .createQueryBuilder('lead')
                .leftJoin('lead.business', 'business')
                .leftJoin('lead.status', 'status')
                .where('lead.statusId = :statusId', { statusId })
                .andWhere('lead.teamId = :teamId', { teamId })
                .andWhere('lead.createdAt BETWEEN :startOfDay AND :endOfDay', { startOfDay, endOfDay })
                .andWhere('business.id IN (:...businessesIds)', { businessesIds });

            const currentCount = await currentQuery.getCount();

            const previousQuery = this.leadsRepository
                .createQueryBuilder('lead')
                .leftJoin('lead.business', 'business')
                .leftJoin('lead.status', 'status')
                .where('lead.statusId = :statusId', { statusId })
                .andWhere('lead.teamId = :teamId', { teamId })
                .andWhere('lead.createdAt BETWEEN :previousStart AND :previousEnd', { previousStart, previousEnd })
                .andWhere('business.id IN (:...businessesIds)', { businessesIds });

            const previousCount = await previousQuery.getCount();

            let percentageChange;

            if (previousCount !== 0) {
                percentageChange = ((currentCount - previousCount) / previousCount) * 100;
            } else if (currentCount !== 0) {
                percentageChange = 100 * currentCount;
            } else {
                percentageChange = 0;
            }

            result.push({
                name: status.name,
                current: currentCount,
                percentageChange: Math.round(percentageChange),
                color: status.primaryColor,
                backgroundColor: status.secondaryColor,
            });
        }
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://intercode.gitbook.io/intercode-saas-kit/pages/dashboard/lead-count-over-period-widget.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
