Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | 1x 1x 1x 1x 1x 13x 13x 13x 13x 13x 13x 4x 13x 3x 3x 13x 13x 1x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 1x 6x 7x 7x 1x 31x 31x 31x 31x 31x 31x 31x 31x 31x 1x 30x 31x 31x 1x 3x 3x 3x 3x 3x 1x 2x 3x 3x 3x 1x 3x 3x 3x 3x 3x 3x 3x 1x 1x 2x 2x | import {
CommentListItemResponse,
ExportFormat,
FeedbackVisibility,
MealCommentCardProps,
MealCommentDisplay,
MealMenuComment,
} from '@/types';
import { EXPORT_FILENAME_PREFIX } from '@/constants';
import { normalizeDateString } from './date';
import { sentimentStore } from '@/stores/sentiment';
/**
* Builds the comments export filename, optionally tagged with the selected date(s).
* Example: Feedback_Report_2026-06-01_to_2026-06-12.xlsx
* */
export const buildExportFilename = (
format: ExportFormat,
fromDate?: string,
toDate?: string,
): string => {
let dateRange = '';
if (fromDate && toDate && fromDate !== toDate) {
dateRange = `_${fromDate}_to_${toDate}`;
} else if (fromDate || toDate) {
dateRange = `_${fromDate ?? toDate}`;
}
return `${EXPORT_FILENAME_PREFIX}${dateRange}.${format}`;
};
export const mapMealCommentToCardProps = (
comment: MealMenuComment,
userName: string,
avatarUrl: string,
): MealCommentDisplay => ({
isComment: true,
commentId: comment.id,
feedback: comment.content,
createdTime: normalizeDateString(comment.createdAt),
authorName: userName,
avatarUrl,
visibility: comment.isAnonymous
? FeedbackVisibility.Anonymous
: FeedbackVisibility.Public,
feedbackSentiment: comment.sentiment ?? null,
});
export const mapCommentListItemToDisplay = (
item: CommentListItemResponse,
): MealCommentDisplay => ({
isComment: true,
commentId: item.id,
feedback: item.content,
createdTime: normalizeDateString(item.createdAt),
authorName: item.isAnonymous ? '' : (item.userInfo?.name ?? ''),
avatarUrl: item.isAnonymous ? '' : (item.userInfo?.avatar ?? ''),
visibility: item.isAnonymous
? FeedbackVisibility.Anonymous
: FeedbackVisibility.Public,
feedbackSentiment: item.sentiment,
});
export const syncCommentToDisplay = (comment: {
id: string;
content: string;
isAnonymous: boolean;
sentiment: string | null;
}) => {
if (comment.sentiment) sentimentStore.setData(comment.id, comment.sentiment);
return {
feedback: comment.content,
visibility: comment.isAnonymous
? FeedbackVisibility.Anonymous
: FeedbackVisibility.Public,
sentiment: comment.sentiment,
};
};
/** Resolves Card comment props for a menu day from the fetched comments list. */
export const getMealCommentCardProps = (
menuId: string,
comments: MealMenuComment[],
userName = '',
avatarUrl = '',
): MealCommentCardProps => {
const comment = comments.find((entry) => entry.menuId === menuId);
if (!comment) {
return { isComment: false };
}
return mapMealCommentToCardProps(comment, userName, avatarUrl);
};
|