Intercode SaaS Kit
  • Welcome to SaaS Starter Kit
  • Getting Started
    • Technology stack
    • Database Setup
    • Local Environment Setup
  • Basics
    • Dependencies
    • App architecture
    • Deployment
    • App roles
    • Endpoints List
      • Auth
      • Two Factor Auth
      • Businesses
      • Demo
      • Email
      • Export Document
      • Email Files
      • Files Demo
      • Leads
      • Orders
      • Payments
      • Subscriptions
      • Teams
      • Team Memberships
      • User Admin
  • Animation and Styles
    • Framer Motion
    • Ant Design and Styles
  • Pages
    • Auth
      • Working with PassportJS
      • Two-Factor Auth
      • OAuth Providers
    • Leads
    • Businesses
    • Team management
      • Ownership
    • Profile
    • User Settings
      • App Tour
    • App Settings
      • Lead Statuses
    • Dashboard
      • Lead volume widget
      • Doughnut chart widget
      • Recent leads table widget
      • Lead count over period widget
    • Demo
  • Features
    • Impersonation
    • Subscriptions (Stripe)
    • Search
    • Sentry
    • Captcha
    • Audit Logs
    • Internationalization
  • External integrations
    • Mailer
    • Google oAuth2
    • Facebook oAuth2
    • S3 compatible storage (AWS, MinIO)
Powered by GitBook
On this page
  1. Pages
  2. Dashboard

Doughnut chart widget

ui/src/components/adminDashboard/widgets/DoughnutChartWidget

DoughnutChartWidget is a side widget which is displaying amount of leads for each choosen business.

Data set and fetch perform the same as on other widgets.

For correct display of label inside a chart we should add a custom plugin which will draw a text exactly at the DoughtnutChart center:

const doughnutLabel = {
        id: 'dounghnutLabel',
        afterDatasetsDraw(chart, args, plugins) {
            const { ctx } = chart;

            const centerX = chart.getDatasetMeta(0).data[0].x;
            const centerY = chart.getDatasetMeta(0).data[0].y;

            ctx.save();
            ctx.font = `500 ${fontSize.lg} Inter`;
            ctx.fillStyle = primitiveColors.gray900;
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText(title, centerX, centerY);
        },
    };

Also for correct display of labels exactly on chart we will use custom plugin ChartDataLabels from chartjs-plugin-datalabels library. Then we write plugin to chart options and add dataLabels styles:

                    plugins: {
                        tooltip: {
                            enabled: false,
                        },
                        datalabels: {
                            display: true,
                            backgroundColor: function (context) {
                                return primitiveColors.gray0;
                            },
                            backgroundShadowColor: colors.black,
                            borderColor: primitiveColors.gray100,
                            borderRadius: 8,
                            borderWidth: 1,
                            color: colors.black,
                            font: {
                                family: 'Inter',
                                weight: 500,
                                size: 16,
                            },
                            padding: {
                                top: 2,
                                bottom: 2,
                                left: 8,
                                right: 8,
                            },
                            shadowOffsetX: 0,
                            shadowOffsetY: 3,
                            shadowBlur: 5,
                            shadowColor: colors.black,
                        },

Backend

On backend we have a function getLeadsPerBusinesses that return us required dataset:

async getLeadsPerBusinesses(
        startDate: string,
        endDate: string,
        businessIds: number[],
        teamId: string
    ): Promise<{ [businessName: string]: number }> {
        const start = dayjs(startDate).startOf('day').toDate();
        const end = dayjs(endDate).endOf('day').toDate();

        if (!start || !end) {
            throw new BadRequestException('Invalid date format');
        }

        const leadsData = await this.leadsRepository
            .createQueryBuilder('lead')
            .innerJoin('lead.business', 'business')
            .select('business.name', 'businessName')
            .addSelect('COUNT(lead.id)', 'leadCount')
            .where('lead.createdAt BETWEEN :start AND :end', { start, end })
            .andWhere('lead.teamId = :teamId', { teamId })
            .andWhere('business.id IN (:...businessIds)', { businessIds })
            .groupBy('business.name')
            .getRawMany();

        const result: { [businessName: string]: number } = {};
        leadsData.forEach(row => {
            result[row.businessName] = parseInt(row.leadCount, 10);
        });

        return result;
    }

Here is used query that will count leads for each business based on their createdAt column. The result of query will be an array of following objects:

{ businessName: 'Retail', leadCount: '126' }

Because of that here used a loop which will combine data in acceptable way for DoughnutChart.

PreviousLead volume widgetNextRecent leads table widget

Last updated 5 months ago