151 lines
3.9 KiB
TypeScript
151 lines
3.9 KiB
TypeScript
/**
|
|
* @prettier
|
|
*/
|
|
import moment from 'moment';
|
|
import { compact, groupBy, sortBy } from 'lodash';
|
|
|
|
import { Message } from './propTypes/Message';
|
|
// import { missingCaseError } from '../../../util/missingCaseError';
|
|
|
|
type StaticSectionType = 'today' | 'yesterday' | 'thisWeek' | 'thisMonth';
|
|
type YearMonthSectionType = 'yearMonth';
|
|
|
|
interface GenericSection<T> {
|
|
type: T;
|
|
messages: Array<Message>;
|
|
}
|
|
type StaticSection = GenericSection<StaticSectionType>;
|
|
type YearMonthSection = GenericSection<YearMonthSectionType> & {
|
|
year: number;
|
|
month: number;
|
|
};
|
|
export type Section = StaticSection | YearMonthSection;
|
|
export const groupMessagesByDate = (
|
|
timestamp: number,
|
|
messages: Array<Message>
|
|
): Array<Section> => {
|
|
const referenceDateTime = moment.utc(timestamp);
|
|
|
|
const sortedMessages = sortBy(messages, message => -message.received_at);
|
|
const messagesWithSection = sortedMessages.map(
|
|
withSection(referenceDateTime)
|
|
);
|
|
const groupedMessages = groupBy(messagesWithSection, 'type');
|
|
const yearMonthMessages = Object.values(
|
|
groupBy(groupedMessages.yearMonth, 'order')
|
|
).reverse();
|
|
return compact([
|
|
toSection(groupedMessages.today),
|
|
toSection(groupedMessages.yesterday),
|
|
toSection(groupedMessages.thisWeek),
|
|
toSection(groupedMessages.thisMonth),
|
|
...yearMonthMessages.map(toSection),
|
|
]);
|
|
};
|
|
|
|
const toSection = (
|
|
messagesWithSection: Array<MessageWithSection> | undefined
|
|
): Section | null => {
|
|
if (!messagesWithSection || messagesWithSection.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
const firstMessageWithSection: MessageWithSection = messagesWithSection[0];
|
|
if (!firstMessageWithSection) {
|
|
return null;
|
|
}
|
|
|
|
const messages = messagesWithSection.map(
|
|
messageWithSection => messageWithSection.message
|
|
);
|
|
switch (firstMessageWithSection.type) {
|
|
case 'today':
|
|
case 'yesterday':
|
|
case 'thisWeek':
|
|
case 'thisMonth':
|
|
return {
|
|
type: firstMessageWithSection.type,
|
|
messages,
|
|
};
|
|
case 'yearMonth':
|
|
return {
|
|
type: firstMessageWithSection.type,
|
|
year: firstMessageWithSection.year,
|
|
month: firstMessageWithSection.month,
|
|
messages,
|
|
};
|
|
default:
|
|
// NOTE: Investigate why we get the following error:
|
|
// error TS2345: Argument of type 'any' is not assignable to parameter
|
|
// of type 'never'.
|
|
// return missingCaseError(firstMessageWithSection.type);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
interface GenericMessageWithSection<T> {
|
|
order: number;
|
|
type: T;
|
|
message: Message;
|
|
}
|
|
type MessageWithStaticSection = GenericMessageWithSection<StaticSectionType>;
|
|
type MessageWithYearMonthSection = GenericMessageWithSection<
|
|
YearMonthSectionType
|
|
> & {
|
|
year: number;
|
|
month: number;
|
|
};
|
|
type MessageWithSection =
|
|
| MessageWithStaticSection
|
|
| MessageWithYearMonthSection;
|
|
|
|
const withSection = (referenceDateTime: moment.Moment) => (
|
|
message: Message
|
|
): MessageWithSection => {
|
|
const today = moment(referenceDateTime).startOf('day');
|
|
const yesterday = moment(referenceDateTime)
|
|
.subtract(1, 'day')
|
|
.startOf('day');
|
|
const thisWeek = moment(referenceDateTime).startOf('isoWeek');
|
|
const thisMonth = moment(referenceDateTime).startOf('month');
|
|
|
|
const messageReceivedDate = moment.utc(message.received_at);
|
|
if (messageReceivedDate.isAfter(today)) {
|
|
return {
|
|
order: 0,
|
|
type: 'today',
|
|
message,
|
|
};
|
|
}
|
|
if (messageReceivedDate.isAfter(yesterday)) {
|
|
return {
|
|
order: 1,
|
|
type: 'yesterday',
|
|
message,
|
|
};
|
|
}
|
|
if (messageReceivedDate.isAfter(thisWeek)) {
|
|
return {
|
|
order: 2,
|
|
type: 'thisWeek',
|
|
message,
|
|
};
|
|
}
|
|
if (messageReceivedDate.isAfter(thisMonth)) {
|
|
return {
|
|
order: 3,
|
|
type: 'thisMonth',
|
|
message,
|
|
};
|
|
}
|
|
|
|
const month: number = messageReceivedDate.month();
|
|
const year: number = messageReceivedDate.year();
|
|
return {
|
|
order: year * 100 + month,
|
|
type: 'yearMonth',
|
|
month,
|
|
year,
|
|
message,
|
|
};
|
|
};
|