onebeyond/bamboohrbot

View on GitHub
src/blockBuilders/employeesCelebrationsBlockBuilder.ts

Summary

Maintainability
D
1 day
Test Coverage
import moment from 'moment';

import defaultMessage from '../constants/defaultMessage';
import { TBambooHREmployeeExtended, TSlackBlock, TSlackMessage } from '..';
import { FRIDAY_ISO_WEEKDAY } from '../common';
import { ordinalSuffix } from '../utils/ordinalSuffix';

export default function employeesCelebrationsBlockBuilder(
  employees: TBambooHREmployeeExtended[],
  today: moment.Moment
): TSlackMessage {
  const firstDayBlocks = buildFirstDayBlocks(employees, today);
  const birthdaysBlocks = buildBirthdaysBlocks(employees, today);
  const anniversariesBlocks = buildAnniversariesBlocks(employees, today);

  return buildMessageToSend([
    ...firstDayBlocks,
    ...birthdaysBlocks,
    ...anniversariesBlocks,
  ]);
}

const buildMessageToSend = (
  messages: TSlackBlock[]
): { text: string; blocks: TSlackBlock[] } => {
  const base = {
    text: "🥳 Let's celebrate together",
    blocks: [
      {
        type: 'header',
        text: {
          type: 'plain_text',
          text: "🥳 Let's celebrate together",
          emoji: true,
        },
      },
    ],
  };

  return messages.length > 0
    ? {
        ...base,
        blocks: [...base.blocks, ...messages],
      }
    : {
        ...base,
        blocks: [...base.blocks, defaultMessage],
      };
};

const buildFirstDayBlocks = (
  employees: TBambooHREmployeeExtended[],
  today: moment.Moment
): TSlackBlock[] => {
  const firstDayEmployees = employees
    .filter(employee => moment(employee.hireDate).isValid())
    .filter(employee => moment(employee.hireDate).isSame(today, 'day'));

  const firstDayBlocks = [];
  if (firstDayEmployees.length > 0) {
    firstDayBlocks.push({
      type: 'context',
      elements: [
        {
          type: 'mrkdwn',
          text: '*First day at One Beyond*',
        },
      ],
    });

    firstDayBlocks.push(
      ...firstDayEmployees.map(employee => ({
        type: 'context',
        elements: [
          employee.photoUrl
            ? {
                type: 'image',
                image_url: employee.photoUrl,
                alt_text: 'employee avatar',
              }
            : {
                type: 'plain_text',
                text: ':bust_in_silhouette:',
              },
          {
            type: 'mrkdwn',
            text: `*Welcome, ${employee.displayName}!*`,
          },
        ],
      }))
    );

    firstDayBlocks.push({
      type: 'divider',
    });
  }
  return firstDayBlocks;
};

const buildBirthdaysBlocks = (
  employees: TBambooHREmployeeExtended[],
  today: moment.Moment
): TSlackBlock[] => {
  const birthdays = employees
    .filter(employee => employee.birthday)
    .reduce<TBambooHREmployeeExtended[]>((previousValue, employee) => {
      const birthdayWithCurrentYear: string = `${today.year()}-${
        employee.birthday
      }`;

      if (!moment(birthdayWithCurrentYear).isValid()) {
        return previousValue;
      }

      if (
        today.isoWeekday() <= FRIDAY_ISO_WEEKDAY &&
        moment(birthdayWithCurrentYear).isSame(today, 'day')
      ) {
        return previousValue.concat(employee);
      }

      if (
        today.isoWeekday() === FRIDAY_ISO_WEEKDAY &&
        moment(birthdayWithCurrentYear).isBetween(
          moment(today).add(1, 'days'),
          moment(today).add(2, 'days'),
          'day',
          '[]'
        )
      ) {
        return previousValue.concat({
          ...employee,
          birthdayOn: moment(birthdayWithCurrentYear).format('dddd'),
        });
      }

      return previousValue;
    }, []);

  const birthdaysBlocks = [];

  if (birthdays.length > 0) {
    birthdaysBlocks.push({
      type: 'context',
      elements: [
        {
          type: 'mrkdwn',
          text: '*Happy birthday!*',
        },
      ],
    });

    birthdaysBlocks.push(
      ...birthdays.map(employee => ({
        type: 'context',
        elements: [
          employee.photoUrl
            ? {
                type: 'image',
                image_url: employee.photoUrl,
                alt_text: 'employee avatar',
              }
            : {
                type: 'plain_text',
                text: ':bust_in_silhouette:',
              },
          {
            type: 'mrkdwn',
            text: `*Happy birthday ${
              employee.birthdayOn ? `on ${employee.birthdayOn}` : ''
            }, ${employee.displayName}!*`,
          },
        ],
      }))
    );
    birthdaysBlocks.push({
      type: 'divider',
    });
  }
  return birthdaysBlocks;
};

const buildAnniversariesBlocks = (
  employees: TBambooHREmployeeExtended[],
  today: moment.Moment
): TSlackBlock[] => {
  const anniversaries = employees
    .filter(employee => moment(employee.hireDate).isValid())
    .reduce<TBambooHREmployeeExtended[]>((previousValue, employee) => {
      const hireDateYear = moment(employee.hireDate).year();
      const hireDateMonth = (moment(employee.hireDate).month() + 1)
        .toString()
        .padStart(2, '0');
      const hireDateDay = moment(employee.hireDate)
        .date()
        .toString()
        .padStart(2, '0');
      const hireDateWithCurrentYear = `${today.year()}-${hireDateMonth}-${hireDateDay}`;

      if (!moment(hireDateWithCurrentYear).isValid()) return previousValue;

      if (hireDateYear === today.year()) return previousValue;

      if (
        today.isoWeekday() <= FRIDAY_ISO_WEEKDAY &&
        moment(hireDateWithCurrentYear).isSame(today, 'day')
      ) {
        return previousValue.concat({
          ...employee,
          anniversary: ordinalSuffix(
            today.year() - moment(employee.hireDate).year()
          ),
        });
      }

      if (
        today.isoWeekday() === FRIDAY_ISO_WEEKDAY &&
        moment(hireDateWithCurrentYear).isBetween(
          moment(today).add(1, 'days'),
          moment(today).add(2, 'days'),
          'day',
          '[]'
        )
      ) {
        return previousValue.concat({
          ...employee,
          anniversary: ordinalSuffix(
            today.year() - moment(employee.hireDate).year()
          ),
          anniversaryOn: moment(hireDateWithCurrentYear).format('dddd'),
        });
      }

      return previousValue;
    }, []);

  const anniversariesBlocks = [];

  if (anniversaries.length > 0) {
    anniversariesBlocks.push({
      type: 'context',
      elements: [
        {
          type: 'mrkdwn',
          text: '*Happy anniversary!*',
        },
      ],
    });

    anniversariesBlocks.push(
      ...anniversaries.map(employee => ({
        type: 'context',
        elements: [
          employee.photoUrl
            ? {
                type: 'image',
                image_url: employee.photoUrl,
                alt_text: 'employee avatar',
              }
            : {
                type: 'plain_text',
                text: ':bust_in_silhouette:',
              },
          {
            type: 'mrkdwn',
            text: `*Happy ${employee.anniversary} anniversary ${
              employee.anniversaryOn ? `on ${employee.anniversaryOn}` : ''
            }, ${employee.displayName}!*`,
          },
        ],
      }))
    );

    anniversariesBlocks.push({
      type: 'divider',
    });
  }

  return anniversariesBlocks;
};