@zeniai/client-epic-state 5.3.12-beta0DI → 5.3.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/lib/commonStateTypes/animations.d.ts +1 -1
  2. package/lib/commonStateTypes/animations.js +1 -0
  3. package/lib/entity/task/taskPayload.d.ts +0 -1
  4. package/lib/entity/task/taskPayload.js +0 -1
  5. package/lib/entity/task/taskReducer.d.ts +1 -4
  6. package/lib/entity/task/taskReducer.js +2 -19
  7. package/lib/entity/task/taskState.d.ts +0 -3
  8. package/lib/epic.d.ts +2 -4
  9. package/lib/epic.js +2 -9
  10. package/lib/esm/commonStateTypes/animations.js +1 -0
  11. package/lib/esm/entity/task/taskPayload.js +0 -1
  12. package/lib/esm/entity/task/taskReducer.js +1 -18
  13. package/lib/esm/epic.js +2 -9
  14. package/lib/esm/index.js +5 -8
  15. package/lib/esm/reducer.js +0 -6
  16. package/lib/esm/view/aiCfoView/aiCfoViewReducer.js +65 -3
  17. package/lib/esm/view/aiCfoView/aiCfoViewSelector.js +25 -0
  18. package/lib/esm/view/aiCfoView/epics/transcribeAudioEpic.js +60 -0
  19. package/lib/esm/view/expenseAutomationView/types/transactionGroup.js +10 -5
  20. package/lib/esm/view/taskManager/taskDetailView/taskDetailSelector.js +0 -3
  21. package/lib/esm/view/taskManager/taskListView/taskList.js +0 -6
  22. package/lib/esm/view/taskManager/taskListView/taskListFilterHelpers.js +0 -7
  23. package/lib/esm/view/taskManager/taskListView/taskListSelector.js +11 -27
  24. package/lib/esm/view/taskManager/taskListView/taskListViewHelpers.js +0 -37
  25. package/lib/esm/view/transactionDetail/createTransaction/createTransactionPayload.js +19 -3
  26. package/lib/esm/view/transactionDetail/createTransaction/createTransactionState.js +2 -0
  27. package/lib/index.d.ts +6 -10
  28. package/lib/index.js +28 -37
  29. package/lib/reducer.d.ts +0 -2
  30. package/lib/reducer.js +0 -6
  31. package/lib/rootStateTypes.d.ts +0 -4
  32. package/lib/view/aiCfoView/aiCfoViewPayload.d.ts +20 -0
  33. package/lib/view/aiCfoView/aiCfoViewReducer.d.ts +2 -2
  34. package/lib/view/aiCfoView/aiCfoViewReducer.js +66 -4
  35. package/lib/view/aiCfoView/aiCfoViewSelector.d.ts +8 -1
  36. package/lib/view/aiCfoView/aiCfoViewSelector.js +27 -0
  37. package/lib/view/aiCfoView/aiCfoViewState.d.ts +9 -0
  38. package/lib/view/aiCfoView/epics/transcribeAudioEpic.d.ts +19 -0
  39. package/lib/view/aiCfoView/epics/transcribeAudioEpic.js +64 -0
  40. package/lib/view/expenseAutomationView/payload/transactionCategorizationPayload.d.ts +2 -2
  41. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.d.ts +2 -2
  42. package/lib/view/expenseAutomationView/types/transactionGroup.d.ts +6 -6
  43. package/lib/view/expenseAutomationView/types/transactionGroup.js +10 -5
  44. package/lib/view/expenseAutomationView/types/transactionsViewState.d.ts +2 -2
  45. package/lib/view/taskManager/taskDetailView/taskDetailSelector.d.ts +0 -4
  46. package/lib/view/taskManager/taskDetailView/taskDetailSelector.js +0 -3
  47. package/lib/view/taskManager/taskListView/taskList.d.ts +1 -1
  48. package/lib/view/taskManager/taskListView/taskList.js +0 -6
  49. package/lib/view/taskManager/taskListView/taskListFilterHelpers.d.ts +0 -4
  50. package/lib/view/taskManager/taskListView/taskListFilterHelpers.js +1 -9
  51. package/lib/view/taskManager/taskListView/taskListSelector.d.ts +3 -6
  52. package/lib/view/taskManager/taskListView/taskListSelector.js +10 -26
  53. package/lib/view/taskManager/taskListView/taskListViewHelpers.d.ts +1 -1
  54. package/lib/view/taskManager/taskListView/taskListViewHelpers.js +0 -37
  55. package/lib/view/transactionDetail/createTransaction/createTransactionPayload.d.ts +6 -3
  56. package/lib/view/transactionDetail/createTransaction/createTransactionPayload.js +19 -3
  57. package/lib/view/transactionDetail/createTransaction/createTransactionState.d.ts +7 -2
  58. package/lib/view/transactionDetail/createTransaction/createTransactionState.js +2 -0
  59. package/lib/view/transactionDetail/transactionDetailReducer.d.ts +20 -20
  60. package/package.json +1 -1
  61. package/lib/entity/timeEntry/timeEntryPayload.d.ts +0 -26
  62. package/lib/entity/timeEntry/timeEntryPayload.js +0 -2
  63. package/lib/entity/timeEntry/timeEntryReducer.d.ts +0 -8
  64. package/lib/entity/timeEntry/timeEntryReducer.js +0 -76
  65. package/lib/entity/timeEntry/timeEntrySelector.d.ts +0 -10
  66. package/lib/entity/timeEntry/timeEntrySelector.js +0 -32
  67. package/lib/entity/timeEntry/timeEntryState.d.ts +0 -43
  68. package/lib/entity/timeEntry/timeEntryState.js +0 -13
  69. package/lib/esm/entity/timeEntry/timeEntryPayload.js +0 -1
  70. package/lib/esm/entity/timeEntry/timeEntryReducer.js +0 -70
  71. package/lib/esm/entity/timeEntry/timeEntrySelector.js +0 -23
  72. package/lib/esm/entity/timeEntry/timeEntryState.js +0 -8
  73. package/lib/esm/view/taskManager/timeEntryView/epic/fetchTaskCategoriesEpic.js +0 -24
  74. package/lib/esm/view/taskManager/timeEntryView/epic/fetchTimeEntriesEpic.js +0 -73
  75. package/lib/esm/view/taskManager/timeEntryView/epic/writeTimeEntryEpic.js +0 -77
  76. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewPayload.js +0 -1
  77. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewReducer.js +0 -160
  78. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewSelector.js +0 -41
  79. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewState.js +0 -1
  80. package/lib/view/taskManager/timeEntryView/epic/fetchTaskCategoriesEpic.d.ts +0 -18
  81. package/lib/view/taskManager/timeEntryView/epic/fetchTaskCategoriesEpic.js +0 -28
  82. package/lib/view/taskManager/timeEntryView/epic/fetchTimeEntriesEpic.d.ts +0 -23
  83. package/lib/view/taskManager/timeEntryView/epic/fetchTimeEntriesEpic.js +0 -78
  84. package/lib/view/taskManager/timeEntryView/epic/writeTimeEntryEpic.d.ts +0 -23
  85. package/lib/view/taskManager/timeEntryView/epic/writeTimeEntryEpic.js +0 -83
  86. package/lib/view/taskManager/timeEntryView/timeEntryViewPayload.d.ts +0 -27
  87. package/lib/view/taskManager/timeEntryView/timeEntryViewPayload.js +0 -2
  88. package/lib/view/taskManager/timeEntryView/timeEntryViewReducer.d.ts +0 -48
  89. package/lib/view/taskManager/timeEntryView/timeEntryViewReducer.js +0 -164
  90. package/lib/view/taskManager/timeEntryView/timeEntryViewSelector.d.ts +0 -24
  91. package/lib/view/taskManager/timeEntryView/timeEntryViewSelector.js +0 -46
  92. package/lib/view/taskManager/timeEntryView/timeEntryViewState.d.ts +0 -21
  93. package/lib/view/taskManager/timeEntryView/timeEntryViewState.js +0 -5
@@ -53,7 +53,7 @@ const sortTasksList = (tagState, tasksList, sortKey, sortOrder) => {
53
53
  }, sortOrder);
54
54
  return tasksInOrder;
55
55
  };
56
- const getTasksWithUserDetails = ({ taskListState, taskState, userState, userRoleState, addressState, taskIds, tagState, userGroupsState, taskCategoriesById, }) => {
56
+ const getTasksWithUserDetails = ({ taskListState, taskState, userState, userRoleState, addressState, taskIds, tagState, userGroupsState, }) => {
57
57
  const { sortKey, searchText } = taskListState.uiState;
58
58
  const sortOrder = (0, sortOrderPayload_1.getSortOrder)(taskListState.uiState.sortOrder);
59
59
  const tasks = taskIds
@@ -76,11 +76,11 @@ const getTasksWithUserDetails = ({ taskListState, taskState, userState, userRole
76
76
  return undefined;
77
77
  })
78
78
  .filter((value) => value?.name.toLowerCase().includes(searchText.toLowerCase()) === true);
79
- const filteredTaskList = (0, spendManagementFilterHelpers_1.applyAdvancedFiltersOnList)((0, taskListFilterHelpers_1.buildCategoryValueGetter)(taskCategoriesById), tasks, taskListState.filters);
79
+ const filteredTaskList = (0, spendManagementFilterHelpers_1.applyAdvancedFiltersOnList)(taskListFilterHelpers_1.getCategoryValueForTaskList, tasks, taskListState.filters);
80
80
  const sortedTaskList = sortTasksList(tagState, filteredTaskList, sortKey, sortOrder);
81
81
  return sortedTaskList;
82
82
  };
83
- const getTaskListGroupedByGroupName = ({ taskListState, taskState, taskGroupState, taskGroupsIds, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }) => {
83
+ const getTaskListGroupedByGroupName = ({ taskListState, taskState, taskGroupState, taskGroupsIds, userState, userRoleState, addressState, tagState, userGroupsState, }) => {
84
84
  const taskGroupsWithTasksList = taskGroupsIds
85
85
  .map((taskGroupId) => {
86
86
  const taskGroup = (0, taskGroupSelector_1.getTaskGroupById)(taskGroupState, taskGroupId);
@@ -94,7 +94,6 @@ const getTaskListGroupedByGroupName = ({ taskListState, taskState, taskGroupStat
94
94
  taskIds,
95
95
  tagState,
96
96
  userGroupsState,
97
- taskCategoriesById,
98
97
  });
99
98
  if (taskGroup != null) {
100
99
  return {
@@ -126,7 +125,7 @@ const getTaskListGroupedByGroupName = ({ taskListState, taskState, taskGroupStat
126
125
  // Also hides deleted groups, which are empty as a side effect.
127
126
  return sortedTaskGroupsWithTasksList.filter((group) => group.tasks.length > 0);
128
127
  };
129
- const getTaskListGroupedByAssignees = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }) => {
128
+ const getTaskListGroupedByAssignees = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }) => {
130
129
  const assigneeGroups = Object.keys(taskListState.taskIdsByAssignees);
131
130
  const taskGroupsWithTasksList = assigneeGroups.map((groupKey) => {
132
131
  const taskIds = taskListState.taskIdsByAssignees[groupKey];
@@ -139,7 +138,6 @@ const getTaskListGroupedByAssignees = ({ taskListState, taskState, userState, us
139
138
  taskIds,
140
139
  tagState,
141
140
  userGroupsState,
142
- taskCategoriesById,
143
141
  });
144
142
  const assigneeIds = groupKey.split(',');
145
143
  const groupName = (0, userSelector_1.getUsersByUserIds)(userState, assigneeIds)
@@ -158,7 +156,7 @@ const getTaskListGroupedByAssignees = ({ taskListState, taskState, userState, us
158
156
  return taskGroupsWithTasksList.filter((group) => group.tasks.length > 0);
159
157
  };
160
158
  exports.getTaskListGroupedByAssignees = getTaskListGroupedByAssignees;
161
- const getTaskListGroupedByPriority = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }) => {
159
+ const getTaskListGroupedByPriority = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }) => {
162
160
  const taskGroupsWithTasksList = taskState_1.ALL_PRIORITY_CODE.map((groupKey) => {
163
161
  const taskIds = taskListState.taskIdsByPriority[groupKey] ?? [];
164
162
  const tasksWithUserDetails = getTasksWithUserDetails({
@@ -170,7 +168,6 @@ const getTaskListGroupedByPriority = ({ taskListState, taskState, userState, use
170
168
  taskIds,
171
169
  tagState,
172
170
  userGroupsState,
173
- taskCategoriesById,
174
171
  });
175
172
  return {
176
173
  groupName: taskDetailSelector_1.allTaskPriority.find((priority) => priority.code === groupKey)?.name ??
@@ -183,7 +180,7 @@ const getTaskListGroupedByPriority = ({ taskListState, taskState, userState, use
183
180
  return taskGroupsWithTasksList.filter((group) => group.tasks.length > 0);
184
181
  };
185
182
  exports.getTaskListGroupedByPriority = getTaskListGroupedByPriority;
186
- const getTaskListGroupedByStatus = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }) => {
183
+ const getTaskListGroupedByStatus = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }) => {
187
184
  const taskGroupsWithTasksList = taskState_1.ALL_TASK_STATUS_CODE.map((groupKey) => {
188
185
  const taskIds = taskListState.taskIdsByStatus[groupKey] ?? [];
189
186
  const tasksWithUserDetails = getTasksWithUserDetails({
@@ -195,7 +192,6 @@ const getTaskListGroupedByStatus = ({ taskListState, taskState, userState, userR
195
192
  taskIds,
196
193
  tagState,
197
194
  userGroupsState,
198
- taskCategoriesById,
199
195
  });
200
196
  return {
201
197
  groupName: taskDetailSelector_1.allTaskStatus.find((taskStatus) => taskStatus.code === groupKey)
@@ -207,7 +203,7 @@ const getTaskListGroupedByStatus = ({ taskListState, taskState, userState, userR
207
203
  });
208
204
  return taskGroupsWithTasksList.filter((group) => group.tasks.length > 0);
209
205
  };
210
- const getTaskListGroupedByTags = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }) => {
206
+ const getTaskListGroupedByTags = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }) => {
211
207
  const tagGroups = Object.keys(taskListState.taskIdsByTags);
212
208
  const taskGroupsWithTasksList = tagGroups.map((groupKey) => {
213
209
  const taskIds = taskListState.taskIdsByTags[groupKey];
@@ -220,7 +216,6 @@ const getTaskListGroupedByTags = ({ taskListState, taskState, userState, userRol
220
216
  taskIds,
221
217
  tagState,
222
218
  userGroupsState,
223
- taskCategoriesById,
224
219
  });
225
220
  const tagIds = groupKey.split(',');
226
221
  const groupName = (0, tagSelector_1.getTagsByIds)(tagState, tagIds)
@@ -237,7 +232,7 @@ const getTaskListGroupedByTags = ({ taskListState, taskState, userState, userRol
237
232
  });
238
233
  return taskGroupsWithTasksList.filter((group) => group.tasks.length > 0);
239
234
  };
240
- const getTaskListGroupedByDueDate = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }) => {
235
+ const getTaskListGroupedByDueDate = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }) => {
241
236
  const taskGroupsWithTasksList = taskList_1.DUE_DATE_GROUP_KEYS.map((groupKey) => {
242
237
  const taskIds = taskListState.taskIdsByDueDate[groupKey];
243
238
  const tasksWithUserDetails = getTasksWithUserDetails({
@@ -249,7 +244,6 @@ const getTaskListGroupedByDueDate = ({ taskListState, taskState, userState, user
249
244
  taskIds,
250
245
  tagState,
251
246
  userGroupsState,
252
- taskCategoriesById,
253
247
  });
254
248
  return {
255
249
  groupName: groupKey,
@@ -260,7 +254,7 @@ const getTaskListGroupedByDueDate = ({ taskListState, taskState, userState, user
260
254
  });
261
255
  return taskGroupsWithTasksList.filter((group) => group.tasks.length > 0);
262
256
  };
263
- const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRoleState, addressState, taskGroupState, taskGroupsIds, tagState, userGroupsState, taskCategoriesById, }) => {
257
+ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRoleState, addressState, taskGroupState, taskGroupsIds, tagState, userGroupsState, }) => {
264
258
  const { groupByKey } = taskListState.uiState;
265
259
  if (groupByKey === 'groupName') {
266
260
  return getTaskListGroupedByGroupName({
@@ -273,7 +267,6 @@ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRo
273
267
  taskGroupsIds,
274
268
  tagState,
275
269
  userGroupsState,
276
- taskCategoriesById,
277
270
  });
278
271
  }
279
272
  if (groupByKey === 'assignee') {
@@ -285,7 +278,6 @@ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRo
285
278
  addressState,
286
279
  tagState,
287
280
  userGroupsState,
288
- taskCategoriesById,
289
281
  });
290
282
  }
291
283
  if (groupByKey === 'priority') {
@@ -297,7 +289,6 @@ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRo
297
289
  addressState,
298
290
  tagState,
299
291
  userGroupsState,
300
- taskCategoriesById,
301
292
  });
302
293
  }
303
294
  if (groupByKey === 'status') {
@@ -309,7 +300,6 @@ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRo
309
300
  addressState,
310
301
  tagState,
311
302
  userGroupsState,
312
- taskCategoriesById,
313
303
  });
314
304
  }
315
305
  if (groupByKey === 'tag') {
@@ -321,7 +311,6 @@ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRo
321
311
  addressState,
322
312
  tagState,
323
313
  userGroupsState,
324
- taskCategoriesById,
325
314
  });
326
315
  }
327
316
  return getTaskListGroupedByDueDate({
@@ -332,7 +321,6 @@ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRo
332
321
  addressState,
333
322
  tagState,
334
323
  userGroupsState,
335
- taskCategoriesById,
336
324
  });
337
325
  };
338
326
  /**
@@ -357,10 +345,7 @@ const getTaskGroupsWithTaskListMemoized = (0, toolkit_1.createSelector)((state)
357
345
  // invalidate this memo and rebuild a board the user is already using.
358
346
  (state) => tagsAreStructural(state.taskListState.uiState)
359
347
  ? state.tagState
360
- : EMPTY_TAG_STATE, (state) => state.userGroupsState,
361
- // Only the catalog, not the whole timeEntry slice: billing is read off
362
- // the task's category, and a timer tick must not rebuild the board.
363
- (state) => state.timeEntryState.taskCategoriesById, (uiState, filters, taskIdsByGroupsIds, taskIdsByAssignees, taskIdsByPriority, taskIdsByStatus, taskIdsByTags, taskIdsByDueDate, taskState, userState, userRoleState, addressState, taskGroupState, taskGroupsIds, tagState, userGroupsState, taskCategoriesById) => getTaskGroupsWithTaskList({
348
+ : EMPTY_TAG_STATE, (state) => state.userGroupsState, (uiState, filters, taskIdsByGroupsIds, taskIdsByAssignees, taskIdsByPriority, taskIdsByStatus, taskIdsByTags, taskIdsByDueDate, taskState, userState, userRoleState, addressState, taskGroupState, taskGroupsIds, tagState, userGroupsState) => getTaskGroupsWithTaskList({
364
349
  taskListState: {
365
350
  uiState,
366
351
  filters,
@@ -379,7 +364,6 @@ const getTaskGroupsWithTaskListMemoized = (0, toolkit_1.createSelector)((state)
379
364
  taskGroupsIds,
380
365
  tagState,
381
366
  userGroupsState,
382
- taskCategoriesById,
383
367
  }));
384
368
  exports.getAllTasks = (0, toolkit_1.createSelector)(
385
369
  // `taskState`, `taskGroupState`, `addressState` and `tagState` are gone from
@@ -3,7 +3,7 @@ import { Task } from '../../../entity/task/taskState';
3
3
  import { User } from '../../../entity/user/userState';
4
4
  import { ZeniDate } from '../../../zeniDayJS';
5
5
  import { TaskGroupKey } from './taskList';
6
- export type SubtaskSortKey = 'name' | 'status' | 'assignee' | 'tag' | 'priority' | 'dueDate' | 'timeSpent';
6
+ export type SubtaskSortKey = 'name' | 'status' | 'assignee' | 'tag';
7
7
  export type SubtaskSortOrder = 'asc' | 'desc';
8
8
  export declare const getDueDateValueFromDueDateGroupId: (groupId: string) => ZeniDate;
9
9
  export declare const getTaskUpdates: (groupByKey: TaskGroupKey, groupId: string) => Partial<Task>;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.sortSubtasks = exports.getTaskUpdates = exports.getDueDateValueFromDueDateGroupId = void 0;
4
- const formatMinutesToFromHHMM_1 = require("../../../commonStateTypes/fiscalYearHelpers/formatMinutesToFromHHMM");
5
4
  const zeniDayJS_1 = require("../../../zeniDayJS");
6
5
  const taskDetailSelector_1 = require("../taskDetailView/taskDetailSelector");
7
6
  const taskList_1 = require("./taskList");
@@ -69,11 +68,6 @@ const sortSubtasks = (subtasks, sortKey, sortOrder, userList, tagList) => {
69
68
  return acc;
70
69
  }, {});
71
70
  const unknownStatusRank = taskDetailSelector_1.allTaskStatus.length;
72
- const priorityOrder = taskDetailSelector_1.allTaskPriority.reduce((acc, priority, index) => {
73
- acc[priority.code] = index;
74
- return acc;
75
- }, {});
76
- const unknownPriorityRank = taskDetailSelector_1.allTaskPriority.length;
77
71
  const cmpStr = (a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' });
78
72
  const keyFn = (task) => {
79
73
  if (sortKey === 'name') {
@@ -100,37 +94,6 @@ const sortSubtasks = (subtasks, sortKey, sortOrder, userList, tagList) => {
100
94
  const tag = tagList.find((candidate) => candidate.tagId === firstTagId);
101
95
  return tag?.name ?? '';
102
96
  }
103
- if (sortKey === 'priority') {
104
- // Rank by the canonical order, not the code string: alphabetical would
105
- // sort "high" before "urgent" and read as wrong to anyone scanning it.
106
- return priorityOrder[task.priority?.code] ?? unknownPriorityRank;
107
- }
108
- if (sortKey === 'dueDate') {
109
- // A task with no date is not "earliest", so undated rows belong at the
110
- // bottom in BOTH directions. The comparator negates for 'desc', so one
111
- // fixed sentinel would flip them to the top — the sentinel has to flip
112
- // with the order to survive that negation.
113
- // `dueDate` is already a ZeniDate (dayjs), so valueOf() is the epoch.
114
- // An unparseable date yields NaN, and a NaN comparator leaves the array
115
- // untouched -- the same silent failure the timeSpent branch guards.
116
- // Treat it as undated rather than as a date.
117
- const due = task.dueDate;
118
- const epoch = due?.valueOf();
119
- if (epoch == null || Number.isNaN(epoch)) {
120
- return sortOrder === 'asc'
121
- ? Number.MAX_SAFE_INTEGER
122
- : Number.MIN_SAFE_INTEGER;
123
- }
124
- return epoch;
125
- }
126
- if (sortKey === 'timeSpent') {
127
- // `timeSpent` is an "HHMM" STRING (no colon). Comparing it as text puts
128
- // "1000" before "0900" only by luck of padding, and any malformed value
129
- // makes the converter return NaN -- which a comparator turns into "no
130
- // sort at all", silently. Coerce that to 0.
131
- const minutes = (0, formatMinutesToFromHHMM_1.convertHHMMStrToMinutes)(task.timeSpent ?? '');
132
- return Number.isFinite(minutes) ? minutes : 0;
133
- }
134
97
  return '';
135
98
  };
136
99
  const copy = [...subtasks];
@@ -13,8 +13,9 @@ import { CreateTransactionLocalData } from './createTransactionState';
13
13
  * constant NAMES; ZENI_LINE_DETAIL_TYPE_TO_QBO_LINE_DETAIL_TYPE_MAP converts them for the
14
14
  * body the backend sends on to QuickBooks, never for ours.
15
15
  * 2. The QBO Purchases (check, credit_card_credit) send their reference number as
16
- * `document_number`; a journal entry sends its entry name as `document_id`. Both land on
17
- * QBO's DocNumber, but QBOJournalEntry reads only `document_id`.
16
+ * `document_number`; a journal entry sends its entry name, a bill its bill number and a
17
+ * vendor credit its reference number as `document_id`. All land on QBO's DocNumber, but
18
+ * QBOJournalEntry reads only `document_id`.
18
19
  */
19
20
  export interface CreateTransactionAccountPayload {
20
21
  qbo_id: ID;
@@ -53,10 +54,12 @@ export interface CreateTransactionRemitToAddressPayload {
53
54
  export interface CreateTransactionRequest extends Record<string, unknown> {
54
55
  transaction_date: string;
55
56
  transaction_type: string;
56
- /** journal_entry entry name (QBO DocNumber). */
57
+ /** journal_entry entry name, bill number or vendor_credit reference number (QBO DocNumber). */
57
58
  document_id?: string;
58
59
  /** check / credit_card_credit reference number (QBO Purchase). */
59
60
  document_number?: string;
61
+ /** bill only. */
62
+ due_date?: string;
60
63
  from_account_id?: ID;
61
64
  /** credit_card_credit is modelled as a Purchase with Credit: true. */
62
65
  is_credit?: boolean;
@@ -135,13 +135,29 @@ const prepareCreateTransactionPayload = (state, localData) => {
135
135
  };
136
136
  }
137
137
  const lines = localData.lines.map((line) => toLinePayload(state, line, transactionType));
138
+ const documentIdField = localData.documentNumber != null && localData.documentNumber !== ''
139
+ ? { document_id: localData.documentNumber }
140
+ : {};
138
141
  if (transactionType === 'journal_entry') {
142
+ return { ...base, ...documentIdField, lines };
143
+ }
144
+ // Both post to accounts payable, so they carry no header account or payment type.
145
+ if (transactionType === 'vendor_credit') {
146
+ return {
147
+ ...base,
148
+ vendor_id: toQboVendorId(state, localData.vendorId),
149
+ ...documentIdField,
150
+ lines,
151
+ };
152
+ }
153
+ if (transactionType === 'bill') {
139
154
  return {
140
155
  ...base,
141
- ...(localData.documentNumber != null &&
142
- localData.documentNumber !== '' && {
143
- document_id: localData.documentNumber,
156
+ vendor_id: toQboVendorId(state, localData.vendorId),
157
+ ...(localData.dueDate != null && {
158
+ due_date: localData.dueDate.format(timePeriod_1.DEFAULT_DATE_FORMAT),
144
159
  }),
160
+ ...documentIdField,
145
161
  lines,
146
162
  };
147
163
  }
@@ -9,7 +9,7 @@ import { ZeniDate } from '../../../zeniDayJS';
9
9
  * The transaction types the Create Transaction flow can originate. A narrow subset of
10
10
  * TransactionType -- everything else is read-only and arrives via sync.
11
11
  */
12
- export declare const ALL_CREATABLE_TRANSACTION_TYPES: readonly ["expense", "check", "credit_card_credit", "transfer", "journal_entry"];
12
+ export declare const ALL_CREATABLE_TRANSACTION_TYPES: readonly ["expense", "check", "credit_card_credit", "transfer", "journal_entry", "bill", "vendor_credit"];
13
13
  export type CreatableTransactionType = (typeof ALL_CREATABLE_TRANSACTION_TYPES)[number];
14
14
  /**
15
15
  * The wire shape the create endpoint expects for a check's remit-to address. Deliberately not
@@ -54,8 +54,13 @@ export interface CreateTransactionLocalData {
54
54
  /** Empty for transfer, which has no lines at all. */
55
55
  lines: CreateTransactionLineLocalData[];
56
56
  transactionType: CreatableTransactionType;
57
- /** check / credit_card_credit reference number, or the journal_entry entry name. */
57
+ /**
58
+ * check / credit_card_credit / vendor_credit reference number, journal_entry entry name, or
59
+ * bill number.
60
+ */
58
61
  documentNumber?: string;
62
+ /** bill only. */
63
+ dueDate?: ZeniDate;
59
64
  /** transfer */
60
65
  fromAccountId?: ID;
61
66
  paymentType?: PaymentType;
@@ -11,4 +11,6 @@ exports.ALL_CREATABLE_TRANSACTION_TYPES = [
11
11
  'credit_card_credit',
12
12
  'transfer',
13
13
  'journal_entry',
14
+ 'bill',
15
+ 'vendor_credit',
14
16
  ];
@@ -177,39 +177,39 @@ export declare const downloadAccountingProviderAttachment: import("@reduxjs/tool
177
177
  }, "transactionDetail/deleteSplitLine", never, never>, toggleSplitEditMode: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionId: TransactionID, editMode: boolean], {
178
178
  transactionId: TransactionID;
179
179
  editMode: boolean;
180
- }, "transactionDetail/toggleSplitEditMode", never, never>, initializeCreateTransactionLocalData: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry"], {
181
- transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry";
182
- }, "transactionDetail/initializeCreateTransactionLocalData", never, never>, updateCreateTransactionLocalData: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry", localData: Partial<CreateTransactionLocalData>], {
183
- transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry";
180
+ }, "transactionDetail/toggleSplitEditMode", never, never>, initializeCreateTransactionLocalData: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry"], {
181
+ transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry";
182
+ }, "transactionDetail/initializeCreateTransactionLocalData", never, never>, updateCreateTransactionLocalData: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry", localData: Partial<CreateTransactionLocalData>], {
183
+ transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry";
184
184
  localData: Partial<CreateTransactionLocalData>;
185
- }, "transactionDetail/updateCreateTransactionLocalData", never, never>, updateCreateTransactionLineLocalData: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry", lineId: string, lineUpdates: Partial<CreateTransactionLineLocalData>], {
186
- transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry";
185
+ }, "transactionDetail/updateCreateTransactionLocalData", never, never>, updateCreateTransactionLineLocalData: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry", lineId: string, lineUpdates: Partial<CreateTransactionLineLocalData>], {
186
+ transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry";
187
187
  lineId: string;
188
188
  lineUpdates: Partial<CreateTransactionLineLocalData>;
189
- }, "transactionDetail/updateCreateTransactionLineLocalData", never, never>, addCreateTransactionLine: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry", line?: Partial<CreateTransactionLineLocalData> | undefined], {
190
- transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry";
189
+ }, "transactionDetail/updateCreateTransactionLineLocalData", never, never>, addCreateTransactionLine: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry", line?: Partial<CreateTransactionLineLocalData> | undefined], {
190
+ transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry";
191
191
  line: Partial<CreateTransactionLineLocalData> | undefined;
192
- }, "transactionDetail/addCreateTransactionLine", never, never>, removeCreateTransactionLine: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry", lineId: string], {
193
- transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry";
192
+ }, "transactionDetail/addCreateTransactionLine", never, never>, removeCreateTransactionLine: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry", lineId: string], {
193
+ transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry";
194
194
  lineId: string;
195
- }, "transactionDetail/removeCreateTransactionLine", never, never>, resetCreateTransactionLocalData: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry"], {
196
- transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry";
197
- }, "transactionDetail/resetCreateTransactionLocalData", never, never>, createTransaction: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry"], {
198
- transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry";
195
+ }, "transactionDetail/removeCreateTransactionLine", never, never>, resetCreateTransactionLocalData: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry"], {
196
+ transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry";
197
+ }, "transactionDetail/resetCreateTransactionLocalData", never, never>, createTransaction: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry"], {
198
+ transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry";
199
199
  }, "transactionDetail/createTransaction", never, never>, createTransactionSuccessOrFailure: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[fetchState: FetchState, createdTransactionId?: TransactionID | undefined, error?: ZeniAPIStatus<Record<string, unknown>> | undefined], {
200
200
  fetchState: FetchState;
201
201
  createdTransactionId: TransactionID | undefined;
202
202
  error: ZeniAPIStatus<Record<string, unknown>> | undefined;
203
- }, "transactionDetail/createTransactionSuccessOrFailure", never, never>, setRecommendationsForCreateTransactionLines: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry", lineIds: string[], recommendations: Recommendation[], isAccountingClassesEnabled: boolean], {
204
- transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry";
203
+ }, "transactionDetail/createTransactionSuccessOrFailure", never, never>, setRecommendationsForCreateTransactionLines: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry", lineIds: string[], recommendations: Recommendation[], isAccountingClassesEnabled: boolean], {
204
+ transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry";
205
205
  lineIds: string[];
206
206
  recommendations: Recommendation[];
207
207
  isAccountingClassesEnabled: boolean;
208
- }, "transactionDetail/setRecommendationsForCreateTransactionLines", never, never>, clearRecommendationsForCreateTransactionLines: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry", lineIds: string[]], {
209
- transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry";
208
+ }, "transactionDetail/setRecommendationsForCreateTransactionLines", never, never>, clearRecommendationsForCreateTransactionLines: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry", lineIds: string[]], {
209
+ transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry";
210
210
  lineIds: string[];
211
- }, "transactionDetail/clearRecommendationsForCreateTransactionLines", never, never>, fetchVendorRecommendationsForCreateTransaction: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry", lineIds: string[], entity?: Entity | undefined], {
212
- transactionType: "expense" | "check" | "credit_card_credit" | "transfer" | "journal_entry";
211
+ }, "transactionDetail/clearRecommendationsForCreateTransactionLines", never, never>, fetchVendorRecommendationsForCreateTransaction: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry", lineIds: string[], entity?: Entity | undefined], {
212
+ transactionType: "expense" | "check" | "bill" | "vendor_credit" | "credit_card_credit" | "transfer" | "journal_entry";
213
213
  lineIds: string[];
214
214
  entity: Entity | undefined;
215
215
  }, "transactionDetail/fetchVendorRecommendationsForCreateTransaction", never, never>, createTransactionAttachmentUploadFailure: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[failedAttachmentFileNames: string[]], {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.3.12-beta0DI",
3
+ "version": "5.3.13",
4
4
  "description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/esm/index.js",
@@ -1,26 +0,0 @@
1
- import { ID } from '../../commonStateTypes/common';
2
- /** Exactly what `task-manager` returns. snake_case, API-nullable. */
3
- export interface TimeEntryPayload {
4
- create_time: string;
5
- entry_date: string;
6
- minutes: number;
7
- source: string;
8
- task_id: ID;
9
- time_entry_id: ID;
10
- update_time: string;
11
- user_id: ID;
12
- /** Derived from the category server-side (D15/D22) and READ-ONLY. Null when
13
- * the task has no category, or the category is not yet classified. */
14
- billing_type?: string | null;
15
- created_by?: ID | null;
16
- department?: string | null;
17
- task_category_id?: ID | null;
18
- }
19
- export interface TaskCategoryPayload {
20
- is_active: boolean;
21
- name: string;
22
- task_category_id: ID;
23
- billing_type?: string | null;
24
- service?: string | null;
25
- vertical?: string | null;
26
- }
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,8 +0,0 @@
1
- import { TaskCategoryPayload, TimeEntryPayload } from './timeEntryPayload';
2
- import { TaskCategory, TimeEntry, TimeEntryState } from './timeEntryState';
3
- export declare const initialState: TimeEntryState;
4
- export declare const updateTimeEntries: import("@reduxjs/toolkit").ActionCreatorWithPayload<TimeEntryPayload[], "timeEntry/updateTimeEntries">, removeTimeEntry: import("@reduxjs/toolkit").ActionCreatorWithPayload<string, "timeEntry/removeTimeEntry">, updateTaskCategories: import("@reduxjs/toolkit").ActionCreatorWithPayload<TaskCategoryPayload[], "timeEntry/updateTaskCategories">;
5
- declare const _default: import("redux").Reducer<TimeEntryState>;
6
- export default _default;
7
- export declare function mapTimeEntryPayloadToTimeEntry(payload: TimeEntryPayload): TimeEntry;
8
- export declare function mapTaskCategoryPayloadToTaskCategory(payload: TaskCategoryPayload): TaskCategory;
@@ -1,76 +0,0 @@
1
- "use strict";
2
- var _a;
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.updateTaskCategories = exports.removeTimeEntry = exports.updateTimeEntries = exports.initialState = void 0;
5
- exports.mapTimeEntryPayloadToTimeEntry = mapTimeEntryPayloadToTimeEntry;
6
- exports.mapTaskCategoryPayloadToTaskCategory = mapTaskCategoryPayloadToTaskCategory;
7
- const toolkit_1 = require("@reduxjs/toolkit");
8
- const rootActions_1 = require("../../rootActions");
9
- const zeniDayJS_1 = require("../../zeniDayJS");
10
- const timeEntryState_1 = require("./timeEntryState");
11
- exports.initialState = {
12
- timeEntriesById: {},
13
- taskCategoriesById: {},
14
- };
15
- const timeEntry = (0, toolkit_1.createSlice)({
16
- name: 'timeEntry',
17
- initialState: exports.initialState,
18
- reducers: {
19
- updateTimeEntries(draft, action) {
20
- action.payload.forEach((payload) => {
21
- const latest = mapTimeEntryPayloadToTimeEntry(payload);
22
- const inStore = draft.timeEntriesById[latest.timeEntryId];
23
- // Last-write-wins by updateTime, same as `address`. A weekly fetch and
24
- // a single-entry edit can land in either order.
25
- if (inStore == null || latest.updateTime.isAfter(inStore.updateTime)) {
26
- draft.timeEntriesById[latest.timeEntryId] = latest;
27
- }
28
- });
29
- },
30
- /** A soft delete comes back as a normal entry; the server has already
31
- * dropped it from the totals, so the client drops it from the store
32
- * rather than keeping a row it must then remember to filter. */
33
- removeTimeEntry(draft, action) {
34
- delete draft.timeEntriesById[action.payload];
35
- },
36
- updateTaskCategories(draft, action) {
37
- action.payload.forEach((payload) => {
38
- const category = mapTaskCategoryPayloadToTaskCategory(payload);
39
- draft.taskCategoriesById[category.taskCategoryId] = category;
40
- });
41
- },
42
- },
43
- extraReducers: (builder) => {
44
- builder.addCase(rootActions_1.clearAll, (draft) => {
45
- Object.assign(draft, exports.initialState);
46
- });
47
- },
48
- });
49
- _a = timeEntry.actions, exports.updateTimeEntries = _a.updateTimeEntries, exports.removeTimeEntry = _a.removeTimeEntry, exports.updateTaskCategories = _a.updateTaskCategories;
50
- exports.default = timeEntry.reducer;
51
- function mapTimeEntryPayloadToTimeEntry(payload) {
52
- return {
53
- timeEntryId: payload.time_entry_id,
54
- taskId: payload.task_id,
55
- userId: payload.user_id,
56
- minutes: payload.minutes,
57
- entryDate: (0, zeniDayJS_1.date)(payload.entry_date),
58
- source: (0, timeEntryState_1.toTimeEntrySource)(payload.source),
59
- createTime: (0, zeniDayJS_1.date)(payload.create_time),
60
- updateTime: (0, zeniDayJS_1.date)(payload.update_time),
61
- billingType: (0, timeEntryState_1.toBillingType)(payload.billing_type),
62
- createdBy: payload.created_by ?? undefined,
63
- department: payload.department ?? undefined,
64
- taskCategoryId: payload.task_category_id ?? undefined,
65
- };
66
- }
67
- function mapTaskCategoryPayloadToTaskCategory(payload) {
68
- return {
69
- taskCategoryId: payload.task_category_id,
70
- name: payload.name,
71
- isActive: payload.is_active,
72
- billingType: (0, timeEntryState_1.toBillingType)(payload.billing_type),
73
- service: payload.service ?? undefined,
74
- vertical: payload.vertical ?? undefined,
75
- };
76
- }
@@ -1,10 +0,0 @@
1
- import { ID } from '../../commonStateTypes/common';
2
- import { TaskCategory, TimeEntry, TimeEntryState } from './timeEntryState';
3
- export declare function getTimeEntryById(timeEntryState: TimeEntryState, timeEntryId: ID): TimeEntry | undefined;
4
- export declare function getTimeEntriesByIds(timeEntryState: TimeEntryState, timeEntryIds: ID[]): TimeEntry[];
5
- export declare function getTaskCategoryById(timeEntryState: TimeEntryState, taskCategoryId: ID): TaskCategory | undefined;
6
- /**
7
- * The catalog, ordered service → vertical → name, matching the order the
8
- * server sends so the dropdown reads the same on both sides.
9
- */
10
- export declare function getTaskCategories(timeEntryState: TimeEntryState, includeInactive?: boolean): TaskCategory[];
@@ -1,32 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getTimeEntryById = getTimeEntryById;
7
- exports.getTimeEntriesByIds = getTimeEntriesByIds;
8
- exports.getTaskCategoryById = getTaskCategoryById;
9
- exports.getTaskCategories = getTaskCategories;
10
- const get_1 = __importDefault(require("lodash/get"));
11
- function getTimeEntryById(timeEntryState, timeEntryId) {
12
- return (0, get_1.default)(timeEntryState.timeEntriesById, timeEntryId, undefined);
13
- }
14
- function getTimeEntriesByIds(timeEntryState, timeEntryIds) {
15
- return timeEntryIds
16
- .map((timeEntryId) => getTimeEntryById(timeEntryState, timeEntryId))
17
- .filter((entry) => entry != null);
18
- }
19
- function getTaskCategoryById(timeEntryState, taskCategoryId) {
20
- return (0, get_1.default)(timeEntryState.taskCategoriesById, taskCategoryId, undefined);
21
- }
22
- /**
23
- * The catalog, ordered service → vertical → name, matching the order the
24
- * server sends so the dropdown reads the same on both sides.
25
- */
26
- function getTaskCategories(timeEntryState, includeInactive = false) {
27
- return Object.values(timeEntryState.taskCategoriesById)
28
- .filter((category) => includeInactive || category.isActive)
29
- .sort((left, right) => (left.service ?? '').localeCompare(right.service ?? '') ||
30
- (left.vertical ?? '').localeCompare(right.vertical ?? '') ||
31
- left.name.localeCompare(right.name));
32
- }
@@ -1,43 +0,0 @@
1
- import { ID } from '../../commonStateTypes/common';
2
- import { ZeniDate } from '../../zeniDayJS';
3
- export declare const ALL_TIME_ENTRY_SOURCES: readonly ["timer", "manual", "migration"];
4
- export type TimeEntrySource = (typeof ALL_TIME_ENTRY_SOURCES)[number];
5
- export declare const ALL_BILLING_TYPES: readonly ["billable", "non_billable"];
6
- export type BillingType = (typeof ALL_BILLING_TYPES)[number];
7
- /** Unknown values become `undefined` rather than being cast through.
8
- * A server that gains a source we do not know about must not land an
9
- * unmatched string in a union the UI switches on. */
10
- export declare const toTimeEntrySource: (raw: string | null | undefined) => "manual" | "timer" | "migration" | undefined;
11
- export declare const toBillingType: (raw: string | null | undefined) => "billable" | "non_billable" | undefined;
12
- export interface TimeEntry {
13
- createTime: ZeniDate;
14
- /** The day the work happened, not the day the row was written. The grain is
15
- * a DAY: one row per user per task per day. */
16
- entryDate: ZeniDate;
17
- minutes: number;
18
- taskId: ID;
19
- timeEntryId: ID;
20
- updateTime: ZeniDate;
21
- userId: ID;
22
- /** Snapshotted at write time, never refreshed — reclassifying a category
23
- * must not rewrite an approved week. Read-only to the client. */
24
- billingType?: BillingType;
25
- createdBy?: ID;
26
- department?: string;
27
- source?: TimeEntrySource;
28
- taskCategoryId?: ID;
29
- }
30
- export interface TaskCategory {
31
- isActive: boolean;
32
- name: string;
33
- taskCategoryId: ID;
34
- billingType?: BillingType;
35
- service?: string;
36
- vertical?: string;
37
- }
38
- export interface TimeEntryState {
39
- taskCategoriesById: Record<ID, TaskCategory>;
40
- /** Keyed by id, like every other entity slice. The per-task and per-user
41
- * groupings live in the VIEW slice, because they are queries over this. */
42
- timeEntriesById: Record<ID, TimeEntry>;
43
- }