@rocketlink/crm-model 1.0.125 → 1.0.126

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.
@@ -30,4 +30,9 @@ export declare function addDaysToDateString(value: string, days: number, formatS
30
30
  export declare function subtractDaysFromDateString(value: string, days: number, formatString?: string): string;
31
31
  export declare function addMonthsToDate(date: Date, months: number): Date;
32
32
  export declare function addPeriodToDate(date: Date, period: number, unit: INTERVAL_UNIT): Date;
33
+ export type UiDateInput = Date | string;
34
+ export type FormatDateForUiOptions = {
35
+ includeSeconds?: boolean;
36
+ };
37
+ export declare function formatDateForUi(value: UiDateInput | null | undefined, options?: FormatDateForUiOptions): string;
33
38
  //# sourceMappingURL=dateUtil.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dateUtil.d.ts","sourceRoot":"","sources":["../../src/util/dateUtil.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO;;;;;;;CAOV,CAAC;AAEX,eAAO,MAAM,aAAa;;;CAGhB,CAAC;AACX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC;AAK/E,wBAAgB,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,GAAE,MAAyB,GAAG,MAAM,CAKzF;AAED,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,CAElD;AAED,wBAAgB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,CAE5C;AAED,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,CAEjD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,CAExD;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAGD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGnD;AAKD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAShD;AAKD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,GAAE,MAAyB,GAAG,MAAM,CAM/F;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAKD,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAK5D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAKnE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,GAAE,MAAyB,GAAG,MAAM,CAIhH;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,GAAE,MAAyB,GAAG,MAAM,CAIvH;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAKhE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAUrF"}
1
+ {"version":3,"file":"dateUtil.d.ts","sourceRoot":"","sources":["../../src/util/dateUtil.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO;;;;;;;CAOV,CAAC;AAEX,eAAO,MAAM,aAAa;;;CAGhB,CAAC;AACX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC;AAK/E,wBAAgB,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,GAAE,MAAyB,GAAG,MAAM,CAKzF;AAED,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,CAElD;AAED,wBAAgB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,CAE5C;AAED,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,CAEjD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,CAExD;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAGD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGnD;AAKD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAShD;AAKD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,GAAE,MAAyB,GAAG,MAAM,CAM/F;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAKD,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAK5D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAKnE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,GAAE,MAAyB,GAAG,MAAM,CAIhH;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,GAAE,MAAyB,GAAG,MAAM,CAIvH;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAKhE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAUrF;AAMD,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,MAAM,CAAC;AAwDxC,MAAM,MAAM,sBAAsB,GAAG;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAElE,wBAAgB,eAAe,CAC7B,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EACrC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM,CA8BR"}
@@ -20,6 +20,7 @@ exports.addDaysToDateString = addDaysToDateString;
20
20
  exports.subtractDaysFromDateString = subtractDaysFromDateString;
21
21
  exports.addMonthsToDate = addMonthsToDate;
22
22
  exports.addPeriodToDate = addPeriodToDate;
23
+ exports.formatDateForUi = formatDateForUi;
23
24
  const date_fns_1 = require("date-fns");
24
25
  exports.FORMATS = {
25
26
  ISO_DATE: 'yyyy-MM-dd', // "2026-01-07"
@@ -140,3 +141,74 @@ function addPeriodToDate(date, period, unit) {
140
141
  }
141
142
  return date;
142
143
  }
144
+ //"15 Jan 2024, 10:30:40" or "15 Jan 2024, 10:30" or just "15 Jan 2024".
145
+ const parseUiDate = (value) => {
146
+ if (value instanceof Date) {
147
+ const d = value;
148
+ if (Number.isNaN(d.getTime()))
149
+ return null;
150
+ const hasTime = d.getHours() !== 0 ||
151
+ d.getMinutes() !== 0 ||
152
+ d.getSeconds() !== 0 ||
153
+ d.getMilliseconds() !== 0;
154
+ return { date: d, hasTime };
155
+ }
156
+ const raw = String(value).trim();
157
+ if (!raw)
158
+ return null;
159
+ // Explicit "dd.MM.yyyy" (e.g. "31.07.2024") -> date-only
160
+ const dotDateMatch = raw.match(/^(\d{2})\.(\d{2})\.(\d{4})$/);
161
+ if (dotDateMatch) {
162
+ const [, dd, mm, yyyy] = dotDateMatch;
163
+ const d = new Date(Number(yyyy), Number(mm) - 1, Number(dd));
164
+ if (Number.isNaN(d.getTime()))
165
+ return null;
166
+ return { date: d, hasTime: false };
167
+ }
168
+ // Plain ISO date "YYYY-MM-DD" -> date-only
169
+ const isoDateOnlyMatch = raw.match(/^(\d{4})-(\d{2})-(\d{2})$/);
170
+ if (isoDateOnlyMatch) {
171
+ const [, yyyy, mm, dd] = isoDateOnlyMatch;
172
+ const d = new Date(Number(yyyy), Number(mm) - 1, Number(dd));
173
+ if (Number.isNaN(d.getTime()))
174
+ return null;
175
+ return { date: d, hasTime: false };
176
+ }
177
+ // Fallback to native parser for ISO timestamps and other formats.
178
+ const d = new Date(raw);
179
+ if (Number.isNaN(d.getTime()))
180
+ return null;
181
+ // If the original string clearly contained a time (has 'T' or an HH:MM),
182
+ // treat it as having a time component, otherwise fall back to midnight check.
183
+ const explicitTime = /T\d\d?:\d\d/.test(raw) || /\d{1,2}:\d{2}/.test(raw);
184
+ const hasTime = explicitTime ||
185
+ d.getHours() !== 0 ||
186
+ d.getMinutes() !== 0 ||
187
+ d.getSeconds() !== 0 ||
188
+ d.getMilliseconds() !== 0;
189
+ return { date: d, hasTime };
190
+ };
191
+ function formatDateForUi(value, options) {
192
+ if (!value) {
193
+ return '-';
194
+ }
195
+ const parsed = parseUiDate(value);
196
+ if (!parsed) {
197
+ return '-';
198
+ }
199
+ const { date, hasTime } = parsed;
200
+ const includeSeconds = options?.includeSeconds ?? false;
201
+ const day = String(date.getDate()).padStart(2, '0');
202
+ const monthShort = date.toLocaleString('en-US', { month: 'short' });
203
+ const year = date.getFullYear();
204
+ const base = `${day} ${monthShort} ${year}`;
205
+ if (!hasTime) {
206
+ return base;
207
+ }
208
+ const hours = String(date.getHours()).padStart(2, '0');
209
+ const minutes = String(date.getMinutes()).padStart(2, '0');
210
+ const time = includeSeconds
211
+ ? `${hours}:${minutes}:${String(date.getSeconds()).padStart(2, '0')}`
212
+ : `${hours}:${minutes}`;
213
+ return `${base}, ${time}`;
214
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rocketlink/crm-model",
3
- "version": "1.0.125",
3
+ "version": "1.0.126",
4
4
  "description": "Shared DTOs and Models for CRM Rocketlink",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -138,4 +138,101 @@ export function addPeriodToDate(date: Date, period: number, unit: INTERVAL_UNIT)
138
138
  date = addDaysToDate(date, period);
139
139
  }
140
140
  return date;
141
+ }
142
+
143
+ // ============================================
144
+ // UI-friendly formatting (used by admin-ts)
145
+ // ============================================
146
+
147
+ export type UiDateInput = Date | string;
148
+
149
+ //"15 Jan 2024, 10:30:40" or "15 Jan 2024, 10:30" or just "15 Jan 2024".
150
+
151
+ const parseUiDate = (
152
+ value: UiDateInput
153
+ ): { date: Date; hasTime: boolean } | null => {
154
+ if (value instanceof Date) {
155
+ const d = value;
156
+ if (Number.isNaN(d.getTime())) return null;
157
+ const hasTime =
158
+ d.getHours() !== 0 ||
159
+ d.getMinutes() !== 0 ||
160
+ d.getSeconds() !== 0 ||
161
+ d.getMilliseconds() !== 0;
162
+ return { date: d, hasTime };
163
+ }
164
+
165
+ const raw = String(value).trim();
166
+ if (!raw) return null;
167
+
168
+ // Explicit "dd.MM.yyyy" (e.g. "31.07.2024") -> date-only
169
+ const dotDateMatch = raw.match(/^(\d{2})\.(\d{2})\.(\d{4})$/);
170
+ if (dotDateMatch) {
171
+ const [, dd, mm, yyyy] = dotDateMatch;
172
+ const d = new Date(Number(yyyy), Number(mm) - 1, Number(dd));
173
+ if (Number.isNaN(d.getTime())) return null;
174
+ return { date: d, hasTime: false };
175
+ }
176
+
177
+ // Plain ISO date "YYYY-MM-DD" -> date-only
178
+ const isoDateOnlyMatch = raw.match(/^(\d{4})-(\d{2})-(\d{2})$/);
179
+ if (isoDateOnlyMatch) {
180
+ const [, yyyy, mm, dd] = isoDateOnlyMatch;
181
+ const d = new Date(Number(yyyy), Number(mm) - 1, Number(dd));
182
+ if (Number.isNaN(d.getTime())) return null;
183
+ return { date: d, hasTime: false };
184
+ }
185
+
186
+ // Fallback to native parser for ISO timestamps and other formats.
187
+ const d = new Date(raw);
188
+ if (Number.isNaN(d.getTime())) return null;
189
+
190
+ // If the original string clearly contained a time (has 'T' or an HH:MM),
191
+ // treat it as having a time component, otherwise fall back to midnight check.
192
+ const explicitTime = /T\d\d?:\d\d/.test(raw) || /\d{1,2}:\d{2}/.test(raw);
193
+ const hasTime =
194
+ explicitTime ||
195
+ d.getHours() !== 0 ||
196
+ d.getMinutes() !== 0 ||
197
+ d.getSeconds() !== 0 ||
198
+ d.getMilliseconds() !== 0;
199
+
200
+ return { date: d, hasTime };
201
+ };
202
+
203
+ export type FormatDateForUiOptions = { includeSeconds?: boolean };
204
+
205
+ export function formatDateForUi(
206
+ value: UiDateInput | null | undefined,
207
+ options?: FormatDateForUiOptions
208
+ ): string {
209
+ if (!value) {
210
+ return '-';
211
+ }
212
+
213
+ const parsed = parseUiDate(value);
214
+ if (!parsed) {
215
+ return '-';
216
+ }
217
+
218
+ const { date, hasTime } = parsed;
219
+ const includeSeconds = options?.includeSeconds ?? false;
220
+
221
+ const day = String(date.getDate()).padStart(2, '0');
222
+ const monthShort = date.toLocaleString('en-US', { month: 'short' });
223
+ const year = date.getFullYear();
224
+ const base = `${day} ${monthShort} ${year}`;
225
+
226
+ if (!hasTime) {
227
+ return base;
228
+ }
229
+
230
+ const hours = String(date.getHours()).padStart(2, '0');
231
+ const minutes = String(date.getMinutes()).padStart(2, '0');
232
+ const time =
233
+ includeSeconds
234
+ ? `${hours}:${minutes}:${String(date.getSeconds()).padStart(2, '0')}`
235
+ : `${hours}:${minutes}`;
236
+
237
+ return `${base}, ${time}`;
141
238
  }