@mrck-labs/vanaheim-shared 0.1.1 → 0.2.0
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.
- package/README.md +162 -10
- package/dist/atoms/index.d.mts +92 -0
- package/dist/atoms/index.d.ts +92 -0
- package/dist/atoms/index.js +82 -0
- package/dist/atoms/index.js.map +1 -0
- package/dist/atoms/index.mjs +47 -0
- package/dist/atoms/index.mjs.map +1 -0
- package/dist/date/index.d.mts +176 -0
- package/dist/date/index.d.ts +176 -0
- package/dist/date/index.js +347 -0
- package/dist/date/index.js.map +1 -0
- package/dist/date/index.mjs +290 -0
- package/dist/date/index.mjs.map +1 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +600 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +557 -3
- package/dist/index.mjs.map +1 -1
- package/dist/query/index.d.mts +321 -0
- package/dist/query/index.d.ts +321 -0
- package/dist/query/index.js +257 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/index.mjs +232 -0
- package/dist/query/index.mjs.map +1 -0
- package/dist/utils/index.d.mts +2 -1
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +1 -1
- package/dist/utils/index.mjs.map +1 -1
- package/package.json +25 -1
package/dist/index.js
CHANGED
|
@@ -36,29 +36,72 @@ __export(src_exports, {
|
|
|
36
36
|
LINEAR_PRIORITY_COLORS: () => LINEAR_PRIORITY_COLORS,
|
|
37
37
|
LINEAR_PRIORITY_LABELS: () => LINEAR_PRIORITY_LABELS,
|
|
38
38
|
SETTING_KEYS: () => SETTING_KEYS,
|
|
39
|
+
activeSessionAtom: () => activeSessionAtom,
|
|
40
|
+
addDays: () => addDays,
|
|
39
41
|
calculateFocusStats: () => calculateFocusStats,
|
|
40
42
|
calculateLieuBalance: () => calculateLieuBalance,
|
|
41
43
|
calculateMonthlyExpenses: () => calculateMonthlyExpenses,
|
|
42
44
|
calculateMonthlyIncome: () => calculateMonthlyIncome,
|
|
43
45
|
calculateMonthlySavings: () => calculateMonthlySavings,
|
|
44
46
|
calculateSavingsRate: () => calculateSavingsRate,
|
|
47
|
+
elapsedSecondsAtom: () => elapsedSecondsAtom,
|
|
45
48
|
formatCurrency: () => formatCurrency,
|
|
46
49
|
formatDate: () => formatDate,
|
|
50
|
+
formatDateHeader: () => formatDateHeader,
|
|
51
|
+
formatDateLocalized: () => formatDateLocalized,
|
|
52
|
+
formatDateLong: () => formatDateLong,
|
|
53
|
+
formatDateString: () => formatDateString,
|
|
47
54
|
formatDueDate: () => formatDueDate,
|
|
55
|
+
formatDueDateString: () => formatDueDateString,
|
|
56
|
+
formatFullDate: () => formatFullDate,
|
|
57
|
+
formatMonthYear: () => formatMonthYear,
|
|
58
|
+
formatRelativeDueDate: () => formatRelativeDueDate,
|
|
59
|
+
formatRelativePayDate: () => formatRelativePayDate,
|
|
48
60
|
formatRelativeTime: () => formatRelativeTime,
|
|
61
|
+
formatRelativeTimeExtended: () => formatRelativeTimeExtended,
|
|
49
62
|
formatTime: () => formatTime,
|
|
63
|
+
formatTimeHHMM: () => formatTimeHHMM,
|
|
64
|
+
formatTimeLocalized: () => formatTimeLocalized,
|
|
65
|
+
formatTimeWithSeconds: () => formatTimeWithSeconds,
|
|
50
66
|
formatTotalTime: () => formatTotalTime,
|
|
67
|
+
formatWeekRange: () => formatWeekRange,
|
|
68
|
+
formattedElapsedAtom: () => formattedElapsedAtom,
|
|
69
|
+
formattedRemainingAtom: () => formattedRemainingAtom,
|
|
51
70
|
generateId: () => generateId,
|
|
52
71
|
generateRandomColor: () => generateRandomColor,
|
|
53
72
|
generateShortId: () => generateShortId,
|
|
73
|
+
getEndOfDayISO: () => getEndOfDayISO,
|
|
74
|
+
getNextWeek: () => getNextWeek,
|
|
75
|
+
getPreviousWeek: () => getPreviousWeek,
|
|
54
76
|
getRepoName: () => getRepoName,
|
|
77
|
+
getStartOfDayISO: () => getStartOfDayISO,
|
|
78
|
+
getTodayMidnight: () => getTodayMidnight,
|
|
79
|
+
getTodayString: () => getTodayString,
|
|
80
|
+
getTomorrowString: () => getTomorrowString,
|
|
81
|
+
getWeekEnd: () => getWeekEnd,
|
|
82
|
+
getWeekEndString: () => getWeekEndString,
|
|
83
|
+
getWeekStart: () => getWeekStart,
|
|
84
|
+
getWeekStartString: () => getWeekStartString,
|
|
85
|
+
getYesterdayString: () => getYesterdayString,
|
|
86
|
+
isDueSoon: () => isDueSoon,
|
|
55
87
|
isNonEmptyString: () => isNonEmptyString,
|
|
88
|
+
isOverdue: () => isOverdue,
|
|
56
89
|
isPositiveNumber: () => isPositiveNumber,
|
|
90
|
+
isToday: () => isToday,
|
|
57
91
|
isValidCurrency: () => isValidCurrency,
|
|
58
92
|
isValidEmail: () => isValidEmail,
|
|
59
93
|
isValidFrequency: () => isValidFrequency,
|
|
60
94
|
isValidISODate: () => isValidISODate,
|
|
61
95
|
isValidUrl: () => isValidUrl,
|
|
96
|
+
normalizeToMidnight: () => normalizeToMidnight,
|
|
97
|
+
parseLocalDate: () => parseLocalDate,
|
|
98
|
+
progressAtom: () => progressAtom,
|
|
99
|
+
progressPercentAtom: () => progressPercentAtom,
|
|
100
|
+
queryKeys: () => queryKeys,
|
|
101
|
+
remainingSecondsAtom: () => remainingSecondsAtom,
|
|
102
|
+
subtractDays: () => subtractDays,
|
|
103
|
+
targetSecondsAtom: () => targetSecondsAtom,
|
|
104
|
+
timerStatusAtom: () => timerStatusAtom,
|
|
62
105
|
toMonthlyAmount: () => toMonthlyAmount,
|
|
63
106
|
toYearlyAmount: () => toYearlyAmount,
|
|
64
107
|
truncate: () => truncate
|
|
@@ -179,7 +222,7 @@ function formatTotalTime(seconds) {
|
|
|
179
222
|
}
|
|
180
223
|
return `${mins}m`;
|
|
181
224
|
}
|
|
182
|
-
function formatCurrency(amount, currency, locale = "
|
|
225
|
+
function formatCurrency(amount, currency, locale = "de-CH") {
|
|
183
226
|
return new Intl.NumberFormat(locale, {
|
|
184
227
|
style: "currency",
|
|
185
228
|
currency,
|
|
@@ -216,12 +259,12 @@ function formatDueDate(dueDate) {
|
|
|
216
259
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
|
217
260
|
const dueDay = new Date(due);
|
|
218
261
|
dueDay.setHours(0, 0, 0, 0);
|
|
219
|
-
const
|
|
262
|
+
const isOverdue2 = dueDay < today;
|
|
220
263
|
if (dueDay.getTime() === today.getTime()) {
|
|
221
264
|
return { text: "Today", isOverdue: false };
|
|
222
265
|
} else if (dueDay.getTime() === tomorrow.getTime()) {
|
|
223
266
|
return { text: "Tomorrow", isOverdue: false };
|
|
224
|
-
} else if (
|
|
267
|
+
} else if (isOverdue2) {
|
|
225
268
|
const daysAgo = Math.ceil(
|
|
226
269
|
(today.getTime() - dueDay.getTime()) / (1e3 * 60 * 60 * 24)
|
|
227
270
|
);
|
|
@@ -363,6 +406,517 @@ function calculateFocusStats(sessions) {
|
|
|
363
406
|
completionRate
|
|
364
407
|
};
|
|
365
408
|
}
|
|
409
|
+
|
|
410
|
+
// src/query/index.ts
|
|
411
|
+
var queryKeys = {
|
|
412
|
+
// -------------------------------------------------------------------------
|
|
413
|
+
// Expenses
|
|
414
|
+
// -------------------------------------------------------------------------
|
|
415
|
+
expenses: {
|
|
416
|
+
all: ["expenses"],
|
|
417
|
+
lists: () => [...queryKeys.expenses.all, "list"],
|
|
418
|
+
list: (filters) => [...queryKeys.expenses.lists(), filters],
|
|
419
|
+
detail: (id) => [...queryKeys.expenses.all, "detail", id]
|
|
420
|
+
},
|
|
421
|
+
// Expense Categories
|
|
422
|
+
expenseCategories: {
|
|
423
|
+
all: ["expenseCategories"],
|
|
424
|
+
list: () => [...queryKeys.expenseCategories.all, "list"]
|
|
425
|
+
},
|
|
426
|
+
// Expense Payments
|
|
427
|
+
expensePayments: {
|
|
428
|
+
all: ["expensePayments"],
|
|
429
|
+
lists: () => [...queryKeys.expensePayments.all, "list"],
|
|
430
|
+
list: (filters) => [...queryKeys.expensePayments.lists(), filters],
|
|
431
|
+
detail: (id) => [...queryKeys.expensePayments.all, "detail", id]
|
|
432
|
+
},
|
|
433
|
+
// -------------------------------------------------------------------------
|
|
434
|
+
// Income
|
|
435
|
+
// -------------------------------------------------------------------------
|
|
436
|
+
incomes: {
|
|
437
|
+
all: ["incomes"],
|
|
438
|
+
lists: () => [...queryKeys.incomes.all, "list"],
|
|
439
|
+
list: (filters) => [...queryKeys.incomes.lists(), filters],
|
|
440
|
+
detail: (id) => [...queryKeys.incomes.all, "detail", id]
|
|
441
|
+
},
|
|
442
|
+
// Income Categories
|
|
443
|
+
incomeCategories: {
|
|
444
|
+
all: ["incomeCategories"],
|
|
445
|
+
list: () => [...queryKeys.incomeCategories.all, "list"]
|
|
446
|
+
},
|
|
447
|
+
// Income Payments
|
|
448
|
+
incomePayments: {
|
|
449
|
+
all: ["incomePayments"],
|
|
450
|
+
lists: () => [...queryKeys.incomePayments.all, "list"],
|
|
451
|
+
list: (filters) => [...queryKeys.incomePayments.lists(), filters],
|
|
452
|
+
detail: (id) => [...queryKeys.incomePayments.all, "detail", id]
|
|
453
|
+
},
|
|
454
|
+
// Exchange Rates
|
|
455
|
+
exchangeRates: {
|
|
456
|
+
all: ["exchangeRates"],
|
|
457
|
+
list: () => [...queryKeys.exchangeRates.all, "list"]
|
|
458
|
+
},
|
|
459
|
+
// -------------------------------------------------------------------------
|
|
460
|
+
// Focus
|
|
461
|
+
// -------------------------------------------------------------------------
|
|
462
|
+
focusSessions: {
|
|
463
|
+
all: ["focusSessions"],
|
|
464
|
+
lists: () => [...queryKeys.focusSessions.all, "list"],
|
|
465
|
+
list: (filters) => [...queryKeys.focusSessions.lists(), filters],
|
|
466
|
+
today: () => [...queryKeys.focusSessions.all, "today"],
|
|
467
|
+
active: () => [...queryKeys.focusSessions.all, "active"],
|
|
468
|
+
detail: (id) => [...queryKeys.focusSessions.all, "detail", id]
|
|
469
|
+
},
|
|
470
|
+
// Focus Categories
|
|
471
|
+
focusCategories: {
|
|
472
|
+
all: ["focusCategories"],
|
|
473
|
+
list: () => [...queryKeys.focusCategories.all, "list"]
|
|
474
|
+
},
|
|
475
|
+
// -------------------------------------------------------------------------
|
|
476
|
+
// Settings
|
|
477
|
+
// -------------------------------------------------------------------------
|
|
478
|
+
settings: {
|
|
479
|
+
all: ["settings"],
|
|
480
|
+
detail: (key) => [...queryKeys.settings.all, key]
|
|
481
|
+
},
|
|
482
|
+
// -------------------------------------------------------------------------
|
|
483
|
+
// EF Work (Lieu Days & Links)
|
|
484
|
+
// -------------------------------------------------------------------------
|
|
485
|
+
lieuDays: {
|
|
486
|
+
all: ["lieuDays"],
|
|
487
|
+
list: () => [...queryKeys.lieuDays.all, "list"],
|
|
488
|
+
balance: () => [...queryKeys.lieuDays.all, "balance"],
|
|
489
|
+
detail: (id) => [...queryKeys.lieuDays.all, "detail", id]
|
|
490
|
+
},
|
|
491
|
+
efLinks: {
|
|
492
|
+
all: ["efLinks"],
|
|
493
|
+
list: () => [...queryKeys.efLinks.all, "list"],
|
|
494
|
+
detail: (id) => [...queryKeys.efLinks.all, "detail", id]
|
|
495
|
+
},
|
|
496
|
+
// -------------------------------------------------------------------------
|
|
497
|
+
// Banking
|
|
498
|
+
// -------------------------------------------------------------------------
|
|
499
|
+
bankConnections: {
|
|
500
|
+
all: ["bankConnections"],
|
|
501
|
+
list: () => [...queryKeys.bankConnections.all, "list"],
|
|
502
|
+
detail: (id) => [...queryKeys.bankConnections.all, "detail", id]
|
|
503
|
+
},
|
|
504
|
+
bankTransactions: {
|
|
505
|
+
all: ["bankTransactions"],
|
|
506
|
+
lists: () => [...queryKeys.bankTransactions.all, "list"],
|
|
507
|
+
list: (filters) => [...queryKeys.bankTransactions.lists(), filters],
|
|
508
|
+
stats: (connectionId) => [...queryKeys.bankTransactions.all, "stats", connectionId]
|
|
509
|
+
},
|
|
510
|
+
// -------------------------------------------------------------------------
|
|
511
|
+
// Health
|
|
512
|
+
// -------------------------------------------------------------------------
|
|
513
|
+
healthCategories: {
|
|
514
|
+
all: ["healthCategories"],
|
|
515
|
+
list: () => [...queryKeys.healthCategories.all, "list"],
|
|
516
|
+
detail: (id) => [...queryKeys.healthCategories.all, "detail", id]
|
|
517
|
+
},
|
|
518
|
+
healthHabits: {
|
|
519
|
+
all: ["healthHabits"],
|
|
520
|
+
lists: () => [...queryKeys.healthHabits.all, "list"],
|
|
521
|
+
list: (filters) => [...queryKeys.healthHabits.lists(), filters],
|
|
522
|
+
detail: (id) => [...queryKeys.healthHabits.all, "detail", id]
|
|
523
|
+
},
|
|
524
|
+
healthCompletions: {
|
|
525
|
+
all: ["healthCompletions"],
|
|
526
|
+
lists: () => [...queryKeys.healthCompletions.all, "list"],
|
|
527
|
+
list: (filters) => [...queryKeys.healthCompletions.lists(), filters],
|
|
528
|
+
forHabit: (habitId) => [...queryKeys.healthCompletions.all, "habit", habitId],
|
|
529
|
+
forDate: (date) => [...queryKeys.healthCompletions.all, "date", date]
|
|
530
|
+
},
|
|
531
|
+
healthStats: {
|
|
532
|
+
all: ["healthStats"],
|
|
533
|
+
forDate: (date) => [...queryKeys.healthStats.all, date ?? "today"]
|
|
534
|
+
},
|
|
535
|
+
// -------------------------------------------------------------------------
|
|
536
|
+
// Prompts
|
|
537
|
+
// -------------------------------------------------------------------------
|
|
538
|
+
promptCategories: {
|
|
539
|
+
all: ["promptCategories"],
|
|
540
|
+
list: () => [...queryKeys.promptCategories.all, "list"],
|
|
541
|
+
detail: (id) => [...queryKeys.promptCategories.all, "detail", id]
|
|
542
|
+
},
|
|
543
|
+
promptLabels: {
|
|
544
|
+
all: ["promptLabels"],
|
|
545
|
+
list: () => [...queryKeys.promptLabels.all, "list"],
|
|
546
|
+
detail: (id) => [...queryKeys.promptLabels.all, "detail", id]
|
|
547
|
+
},
|
|
548
|
+
prompts: {
|
|
549
|
+
all: ["prompts"],
|
|
550
|
+
lists: () => [...queryKeys.prompts.all, "list"],
|
|
551
|
+
list: (filters) => [...queryKeys.prompts.lists(), filters],
|
|
552
|
+
detail: (id) => [...queryKeys.prompts.all, "detail", id]
|
|
553
|
+
},
|
|
554
|
+
// -------------------------------------------------------------------------
|
|
555
|
+
// Training
|
|
556
|
+
// -------------------------------------------------------------------------
|
|
557
|
+
trainingActivities: {
|
|
558
|
+
all: ["trainingActivities"],
|
|
559
|
+
list: () => [...queryKeys.trainingActivities.all, "list"],
|
|
560
|
+
detail: (id) => [...queryKeys.trainingActivities.all, "detail", id],
|
|
561
|
+
byStravaType: (stravaType) => [...queryKeys.trainingActivities.all, "strava", stravaType]
|
|
562
|
+
},
|
|
563
|
+
trainingSessions: {
|
|
564
|
+
all: ["trainingSessions"],
|
|
565
|
+
lists: () => [...queryKeys.trainingSessions.all, "list"],
|
|
566
|
+
list: (filters) => [...queryKeys.trainingSessions.lists(), filters],
|
|
567
|
+
detail: (id) => [...queryKeys.trainingSessions.all, "detail", id],
|
|
568
|
+
byStravaId: (stravaActivityId) => [...queryKeys.trainingSessions.all, "strava", stravaActivityId]
|
|
569
|
+
},
|
|
570
|
+
plannedSessions: {
|
|
571
|
+
all: ["plannedSessions"],
|
|
572
|
+
lists: () => [...queryKeys.plannedSessions.all, "list"],
|
|
573
|
+
list: (filters) => [...queryKeys.plannedSessions.lists(), filters],
|
|
574
|
+
detail: (id) => [...queryKeys.plannedSessions.all, "detail", id],
|
|
575
|
+
upcoming: () => [...queryKeys.plannedSessions.all, "upcoming"]
|
|
576
|
+
},
|
|
577
|
+
races: {
|
|
578
|
+
all: ["races"],
|
|
579
|
+
lists: () => [...queryKeys.races.all, "list"],
|
|
580
|
+
list: (filters) => [...queryKeys.races.lists(), filters],
|
|
581
|
+
detail: (id) => [...queryKeys.races.all, "detail", id],
|
|
582
|
+
next: () => [...queryKeys.races.all, "next"]
|
|
583
|
+
},
|
|
584
|
+
trainingStats: {
|
|
585
|
+
all: ["trainingStats"],
|
|
586
|
+
forRange: (dateFrom, dateTo) => [...queryKeys.trainingStats.all, dateFrom, dateTo]
|
|
587
|
+
},
|
|
588
|
+
// Strava
|
|
589
|
+
strava: {
|
|
590
|
+
all: ["strava"],
|
|
591
|
+
athlete: () => [...queryKeys.strava.all, "athlete"],
|
|
592
|
+
connected: () => [...queryKeys.strava.all, "connected"],
|
|
593
|
+
activities: (options) => [...queryKeys.strava.all, "activities", options]
|
|
594
|
+
},
|
|
595
|
+
// -------------------------------------------------------------------------
|
|
596
|
+
// Journal
|
|
597
|
+
// -------------------------------------------------------------------------
|
|
598
|
+
journalEntries: {
|
|
599
|
+
all: ["journalEntries"],
|
|
600
|
+
lists: () => [...queryKeys.journalEntries.all, "list"],
|
|
601
|
+
list: (filters) => [...queryKeys.journalEntries.lists(), filters],
|
|
602
|
+
forDate: (date) => [...queryKeys.journalEntries.all, "date", date]
|
|
603
|
+
},
|
|
604
|
+
// Journal data (aggregated)
|
|
605
|
+
journalData: {
|
|
606
|
+
all: ["journalData"],
|
|
607
|
+
forDate: (date) => [...queryKeys.journalData.all, date]
|
|
608
|
+
},
|
|
609
|
+
// -------------------------------------------------------------------------
|
|
610
|
+
// Chat
|
|
611
|
+
// -------------------------------------------------------------------------
|
|
612
|
+
chatConversations: {
|
|
613
|
+
all: ["chatConversations"],
|
|
614
|
+
list: () => [...queryKeys.chatConversations.all, "list"],
|
|
615
|
+
detail: (id) => [...queryKeys.chatConversations.all, "detail", id]
|
|
616
|
+
},
|
|
617
|
+
chatMessages: {
|
|
618
|
+
all: ["chatMessages"],
|
|
619
|
+
forConversation: (conversationId) => [...queryKeys.chatMessages.all, "conversation", conversationId]
|
|
620
|
+
},
|
|
621
|
+
// -------------------------------------------------------------------------
|
|
622
|
+
// Google Calendar
|
|
623
|
+
// -------------------------------------------------------------------------
|
|
624
|
+
googleCalendar: {
|
|
625
|
+
all: ["googleCalendar"],
|
|
626
|
+
calendars: () => [...queryKeys.googleCalendar.all, "calendars"],
|
|
627
|
+
events: (calendarId, timeMin, timeMax) => [...queryKeys.googleCalendar.all, "events", calendarId, timeMin, timeMax]
|
|
628
|
+
},
|
|
629
|
+
// -------------------------------------------------------------------------
|
|
630
|
+
// Linear
|
|
631
|
+
// -------------------------------------------------------------------------
|
|
632
|
+
linear: {
|
|
633
|
+
all: ["linear"],
|
|
634
|
+
issues: (filters) => [...queryKeys.linear.all, "issues", filters],
|
|
635
|
+
projects: () => [...queryKeys.linear.all, "projects"]
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
// src/atoms/focus.ts
|
|
640
|
+
var import_jotai = require("jotai");
|
|
641
|
+
var timerStatusAtom = (0, import_jotai.atom)("idle");
|
|
642
|
+
var targetSecondsAtom = (0, import_jotai.atom)(25 * 60);
|
|
643
|
+
var elapsedSecondsAtom = (0, import_jotai.atom)(0);
|
|
644
|
+
var activeSessionAtom = (0, import_jotai.atom)(null);
|
|
645
|
+
var remainingSecondsAtom = (0, import_jotai.atom)((get) => {
|
|
646
|
+
const target = get(targetSecondsAtom);
|
|
647
|
+
const elapsed = get(elapsedSecondsAtom);
|
|
648
|
+
return Math.max(0, target - elapsed);
|
|
649
|
+
});
|
|
650
|
+
var progressAtom = (0, import_jotai.atom)((get) => {
|
|
651
|
+
const target = get(targetSecondsAtom);
|
|
652
|
+
const elapsed = get(elapsedSecondsAtom);
|
|
653
|
+
if (target === 0) return 0;
|
|
654
|
+
return Math.min(1, elapsed / target);
|
|
655
|
+
});
|
|
656
|
+
var formattedRemainingAtom = (0, import_jotai.atom)((get) => {
|
|
657
|
+
return formatTime(get(remainingSecondsAtom));
|
|
658
|
+
});
|
|
659
|
+
var formattedElapsedAtom = (0, import_jotai.atom)((get) => {
|
|
660
|
+
return formatTime(get(elapsedSecondsAtom));
|
|
661
|
+
});
|
|
662
|
+
var progressPercentAtom = (0, import_jotai.atom)((get) => {
|
|
663
|
+
return get(progressAtom) * 100;
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
// src/date/index.ts
|
|
667
|
+
function normalizeToMidnight(date) {
|
|
668
|
+
const d = new Date(date);
|
|
669
|
+
d.setHours(0, 0, 0, 0);
|
|
670
|
+
return d;
|
|
671
|
+
}
|
|
672
|
+
function getTodayMidnight() {
|
|
673
|
+
return normalizeToMidnight(/* @__PURE__ */ new Date());
|
|
674
|
+
}
|
|
675
|
+
function formatDateString(date) {
|
|
676
|
+
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
|
|
677
|
+
}
|
|
678
|
+
function getTodayString() {
|
|
679
|
+
return formatDateString(/* @__PURE__ */ new Date());
|
|
680
|
+
}
|
|
681
|
+
function parseLocalDate(dateStr) {
|
|
682
|
+
return /* @__PURE__ */ new Date(dateStr + "T00:00:00");
|
|
683
|
+
}
|
|
684
|
+
function isToday(dateStr) {
|
|
685
|
+
if (!dateStr) return false;
|
|
686
|
+
return dateStr === getTodayString();
|
|
687
|
+
}
|
|
688
|
+
function isOverdue(dateStr) {
|
|
689
|
+
if (!dateStr) return false;
|
|
690
|
+
return dateStr < getTodayString();
|
|
691
|
+
}
|
|
692
|
+
function isDueSoon(dateStr, daysThreshold = 7) {
|
|
693
|
+
if (!dateStr) return false;
|
|
694
|
+
if (isOverdue(dateStr)) return false;
|
|
695
|
+
const today = getTodayMidnight();
|
|
696
|
+
const targetDate = parseLocalDate(dateStr);
|
|
697
|
+
const diffMs = targetDate.getTime() - today.getTime();
|
|
698
|
+
const diffDays = Math.ceil(diffMs / (1e3 * 60 * 60 * 24));
|
|
699
|
+
return diffDays >= 0 && diffDays <= daysThreshold;
|
|
700
|
+
}
|
|
701
|
+
function addDays(dateStr, days) {
|
|
702
|
+
const date = parseLocalDate(dateStr);
|
|
703
|
+
date.setDate(date.getDate() + days);
|
|
704
|
+
return formatDateString(date);
|
|
705
|
+
}
|
|
706
|
+
function subtractDays(dateStr, days) {
|
|
707
|
+
return addDays(dateStr, -days);
|
|
708
|
+
}
|
|
709
|
+
function getYesterdayString() {
|
|
710
|
+
return subtractDays(getTodayString(), 1);
|
|
711
|
+
}
|
|
712
|
+
function getTomorrowString() {
|
|
713
|
+
return addDays(getTodayString(), 1);
|
|
714
|
+
}
|
|
715
|
+
function getStartOfDayISO(dateStr) {
|
|
716
|
+
const date = parseLocalDate(dateStr);
|
|
717
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate()).toISOString();
|
|
718
|
+
}
|
|
719
|
+
function getEndOfDayISO(dateStr) {
|
|
720
|
+
const date = parseLocalDate(dateStr);
|
|
721
|
+
return new Date(
|
|
722
|
+
date.getFullYear(),
|
|
723
|
+
date.getMonth(),
|
|
724
|
+
date.getDate(),
|
|
725
|
+
23,
|
|
726
|
+
59,
|
|
727
|
+
59,
|
|
728
|
+
999
|
|
729
|
+
).toISOString();
|
|
730
|
+
}
|
|
731
|
+
function getWeekStart(date) {
|
|
732
|
+
const d = new Date(date);
|
|
733
|
+
const day = d.getDay();
|
|
734
|
+
const diff = d.getDate() - day + (day === 0 ? -6 : 1);
|
|
735
|
+
d.setDate(diff);
|
|
736
|
+
d.setHours(0, 0, 0, 0);
|
|
737
|
+
return d;
|
|
738
|
+
}
|
|
739
|
+
function getWeekEnd(weekStart) {
|
|
740
|
+
const d = new Date(weekStart);
|
|
741
|
+
d.setDate(d.getDate() + 6);
|
|
742
|
+
return d;
|
|
743
|
+
}
|
|
744
|
+
function getPreviousWeek(weekStart) {
|
|
745
|
+
const d = new Date(weekStart);
|
|
746
|
+
d.setDate(d.getDate() - 7);
|
|
747
|
+
return d;
|
|
748
|
+
}
|
|
749
|
+
function getNextWeek(weekStart) {
|
|
750
|
+
const d = new Date(weekStart);
|
|
751
|
+
d.setDate(d.getDate() + 7);
|
|
752
|
+
return d;
|
|
753
|
+
}
|
|
754
|
+
function getWeekStartString(baseDate = /* @__PURE__ */ new Date()) {
|
|
755
|
+
return formatDateString(getWeekStart(baseDate));
|
|
756
|
+
}
|
|
757
|
+
function getWeekEndString(baseDate = /* @__PURE__ */ new Date()) {
|
|
758
|
+
return formatDateString(getWeekEnd(getWeekStart(baseDate)));
|
|
759
|
+
}
|
|
760
|
+
function formatWeekRange(weekStart) {
|
|
761
|
+
const weekEnd = getWeekEnd(weekStart);
|
|
762
|
+
const startMonth = weekStart.toLocaleDateString("en-US", { month: "short" });
|
|
763
|
+
const endMonth = weekEnd.toLocaleDateString("en-US", { month: "short" });
|
|
764
|
+
if (startMonth === endMonth) {
|
|
765
|
+
return `${startMonth} ${weekStart.getDate()} - ${weekEnd.getDate()}, ${weekStart.getFullYear()}`;
|
|
766
|
+
}
|
|
767
|
+
return `${startMonth} ${weekStart.getDate()} - ${endMonth} ${weekEnd.getDate()}, ${weekStart.getFullYear()}`;
|
|
768
|
+
}
|
|
769
|
+
function formatFullDate(dateStr) {
|
|
770
|
+
const date = parseLocalDate(dateStr);
|
|
771
|
+
return date.toLocaleDateString("en-US", {
|
|
772
|
+
weekday: "long",
|
|
773
|
+
year: "numeric",
|
|
774
|
+
month: "long",
|
|
775
|
+
day: "numeric"
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
function formatDateLong(dateStr) {
|
|
779
|
+
const date = parseLocalDate(dateStr);
|
|
780
|
+
return date.toLocaleDateString("en-GB", {
|
|
781
|
+
weekday: "long",
|
|
782
|
+
day: "numeric",
|
|
783
|
+
month: "long"
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
function formatMonthYear(date) {
|
|
787
|
+
return date.toLocaleDateString("en-US", {
|
|
788
|
+
month: "long",
|
|
789
|
+
year: "numeric"
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
function formatTimeHHMM(date) {
|
|
793
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
794
|
+
return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
795
|
+
}
|
|
796
|
+
function formatTimeWithSeconds(date) {
|
|
797
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
798
|
+
return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
|
799
|
+
}
|
|
800
|
+
function formatDateHeader(dateStr) {
|
|
801
|
+
const today = getTodayString();
|
|
802
|
+
if (dateStr < today) {
|
|
803
|
+
return "Overdue";
|
|
804
|
+
}
|
|
805
|
+
if (dateStr === today) {
|
|
806
|
+
return "Today";
|
|
807
|
+
}
|
|
808
|
+
const tomorrowStr = getTomorrowString();
|
|
809
|
+
if (dateStr === tomorrowStr) {
|
|
810
|
+
return "Tomorrow";
|
|
811
|
+
}
|
|
812
|
+
const date = parseLocalDate(dateStr);
|
|
813
|
+
return date.toLocaleDateString("en-US", {
|
|
814
|
+
weekday: "long",
|
|
815
|
+
month: "short",
|
|
816
|
+
day: "numeric"
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
function formatDueDateString(dateStr) {
|
|
820
|
+
if (!dateStr) return "No due date";
|
|
821
|
+
const today = getTodayString();
|
|
822
|
+
const tomorrowStr = getTomorrowString();
|
|
823
|
+
if (dateStr < today) {
|
|
824
|
+
const date2 = parseLocalDate(dateStr);
|
|
825
|
+
return `Overdue \u2022 ${date2.toLocaleDateString("en-US", { month: "short", day: "numeric" })}`;
|
|
826
|
+
}
|
|
827
|
+
if (dateStr === today) {
|
|
828
|
+
return "Today";
|
|
829
|
+
}
|
|
830
|
+
if (dateStr === tomorrowStr) {
|
|
831
|
+
return "Tomorrow";
|
|
832
|
+
}
|
|
833
|
+
const date = parseLocalDate(dateStr);
|
|
834
|
+
const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
|
|
835
|
+
const dateYear = date.getFullYear();
|
|
836
|
+
return date.toLocaleDateString("en-US", {
|
|
837
|
+
month: "short",
|
|
838
|
+
day: "numeric",
|
|
839
|
+
year: dateYear !== currentYear ? "numeric" : void 0
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
function formatRelativeTimeExtended(dateStr) {
|
|
843
|
+
const date = typeof dateStr === "string" ? new Date(dateStr) : dateStr;
|
|
844
|
+
const now = /* @__PURE__ */ new Date();
|
|
845
|
+
const diffMs = now.getTime() - date.getTime();
|
|
846
|
+
const diffMins = Math.floor(diffMs / 6e4);
|
|
847
|
+
const diffHours = Math.floor(diffMins / 60);
|
|
848
|
+
const diffDays = Math.floor(diffHours / 24);
|
|
849
|
+
if (diffMins < 1) return "Just now";
|
|
850
|
+
if (diffMins < 60) return `${diffMins}m ago`;
|
|
851
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
852
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
853
|
+
return date.toLocaleDateString();
|
|
854
|
+
}
|
|
855
|
+
function formatRelativeDueDate(dateStr, options) {
|
|
856
|
+
const { duePrefix = "Due", overduePrefix = "" } = options || {};
|
|
857
|
+
const date = parseLocalDate(dateStr);
|
|
858
|
+
const now = normalizeToMidnight(/* @__PURE__ */ new Date());
|
|
859
|
+
const diffMs = date.getTime() - now.getTime();
|
|
860
|
+
const diffDays = Math.round(diffMs / (1e3 * 60 * 60 * 24));
|
|
861
|
+
if (diffDays < 0) {
|
|
862
|
+
const absDays = Math.abs(diffDays);
|
|
863
|
+
return overduePrefix ? `${overduePrefix} ${absDays} day${absDays !== 1 ? "s" : ""} overdue` : `${absDays} day${absDays !== 1 ? "s" : ""} overdue`;
|
|
864
|
+
}
|
|
865
|
+
if (diffDays === 0) return `${duePrefix} today`;
|
|
866
|
+
if (diffDays === 1) return `${duePrefix} tomorrow`;
|
|
867
|
+
if (diffDays <= 7) return `${duePrefix} in ${diffDays} days`;
|
|
868
|
+
return date.toLocaleDateString("en-GB", { day: "numeric", month: "short" });
|
|
869
|
+
}
|
|
870
|
+
function formatRelativePayDate(dateStr) {
|
|
871
|
+
const date = parseLocalDate(dateStr);
|
|
872
|
+
const now = normalizeToMidnight(/* @__PURE__ */ new Date());
|
|
873
|
+
const diffMs = date.getTime() - now.getTime();
|
|
874
|
+
const diffDays = Math.round(diffMs / (1e3 * 60 * 60 * 24));
|
|
875
|
+
if (diffDays < 0) {
|
|
876
|
+
const absDays = Math.abs(diffDays);
|
|
877
|
+
return `${absDays} day${absDays !== 1 ? "s" : ""} ago`;
|
|
878
|
+
}
|
|
879
|
+
if (diffDays === 0) return "Today";
|
|
880
|
+
if (diffDays === 1) return "Tomorrow";
|
|
881
|
+
if (diffDays <= 7) return `In ${diffDays} days`;
|
|
882
|
+
return date.toLocaleDateString("en-GB", { day: "numeric", month: "short" });
|
|
883
|
+
}
|
|
884
|
+
function formatDateLocalized(date, format = "medium") {
|
|
885
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
886
|
+
switch (format) {
|
|
887
|
+
case "short":
|
|
888
|
+
return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
889
|
+
case "medium":
|
|
890
|
+
return d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
|
|
891
|
+
case "long":
|
|
892
|
+
return d.toLocaleDateString("en-US", {
|
|
893
|
+
weekday: "long",
|
|
894
|
+
month: "long",
|
|
895
|
+
day: "numeric",
|
|
896
|
+
year: "numeric"
|
|
897
|
+
});
|
|
898
|
+
case "weekday":
|
|
899
|
+
return d.toLocaleDateString("en-US", { weekday: "short" });
|
|
900
|
+
default:
|
|
901
|
+
return d.toLocaleDateString();
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
function formatTimeLocalized(date, format = "short") {
|
|
905
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
906
|
+
switch (format) {
|
|
907
|
+
case "short":
|
|
908
|
+
return d.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: true });
|
|
909
|
+
case "withSeconds":
|
|
910
|
+
return d.toLocaleTimeString("en-US", {
|
|
911
|
+
hour: "2-digit",
|
|
912
|
+
minute: "2-digit",
|
|
913
|
+
second: "2-digit",
|
|
914
|
+
hour12: true
|
|
915
|
+
});
|
|
916
|
+
default:
|
|
917
|
+
return d.toLocaleTimeString();
|
|
918
|
+
}
|
|
919
|
+
}
|
|
366
920
|
// Annotate the CommonJS export names for ESM import in node:
|
|
367
921
|
0 && (module.exports = {
|
|
368
922
|
API_URLS,
|
|
@@ -381,29 +935,72 @@ function calculateFocusStats(sessions) {
|
|
|
381
935
|
LINEAR_PRIORITY_COLORS,
|
|
382
936
|
LINEAR_PRIORITY_LABELS,
|
|
383
937
|
SETTING_KEYS,
|
|
938
|
+
activeSessionAtom,
|
|
939
|
+
addDays,
|
|
384
940
|
calculateFocusStats,
|
|
385
941
|
calculateLieuBalance,
|
|
386
942
|
calculateMonthlyExpenses,
|
|
387
943
|
calculateMonthlyIncome,
|
|
388
944
|
calculateMonthlySavings,
|
|
389
945
|
calculateSavingsRate,
|
|
946
|
+
elapsedSecondsAtom,
|
|
390
947
|
formatCurrency,
|
|
391
948
|
formatDate,
|
|
949
|
+
formatDateHeader,
|
|
950
|
+
formatDateLocalized,
|
|
951
|
+
formatDateLong,
|
|
952
|
+
formatDateString,
|
|
392
953
|
formatDueDate,
|
|
954
|
+
formatDueDateString,
|
|
955
|
+
formatFullDate,
|
|
956
|
+
formatMonthYear,
|
|
957
|
+
formatRelativeDueDate,
|
|
958
|
+
formatRelativePayDate,
|
|
393
959
|
formatRelativeTime,
|
|
960
|
+
formatRelativeTimeExtended,
|
|
394
961
|
formatTime,
|
|
962
|
+
formatTimeHHMM,
|
|
963
|
+
formatTimeLocalized,
|
|
964
|
+
formatTimeWithSeconds,
|
|
395
965
|
formatTotalTime,
|
|
966
|
+
formatWeekRange,
|
|
967
|
+
formattedElapsedAtom,
|
|
968
|
+
formattedRemainingAtom,
|
|
396
969
|
generateId,
|
|
397
970
|
generateRandomColor,
|
|
398
971
|
generateShortId,
|
|
972
|
+
getEndOfDayISO,
|
|
973
|
+
getNextWeek,
|
|
974
|
+
getPreviousWeek,
|
|
399
975
|
getRepoName,
|
|
976
|
+
getStartOfDayISO,
|
|
977
|
+
getTodayMidnight,
|
|
978
|
+
getTodayString,
|
|
979
|
+
getTomorrowString,
|
|
980
|
+
getWeekEnd,
|
|
981
|
+
getWeekEndString,
|
|
982
|
+
getWeekStart,
|
|
983
|
+
getWeekStartString,
|
|
984
|
+
getYesterdayString,
|
|
985
|
+
isDueSoon,
|
|
400
986
|
isNonEmptyString,
|
|
987
|
+
isOverdue,
|
|
401
988
|
isPositiveNumber,
|
|
989
|
+
isToday,
|
|
402
990
|
isValidCurrency,
|
|
403
991
|
isValidEmail,
|
|
404
992
|
isValidFrequency,
|
|
405
993
|
isValidISODate,
|
|
406
994
|
isValidUrl,
|
|
995
|
+
normalizeToMidnight,
|
|
996
|
+
parseLocalDate,
|
|
997
|
+
progressAtom,
|
|
998
|
+
progressPercentAtom,
|
|
999
|
+
queryKeys,
|
|
1000
|
+
remainingSecondsAtom,
|
|
1001
|
+
subtractDays,
|
|
1002
|
+
targetSecondsAtom,
|
|
1003
|
+
timerStatusAtom,
|
|
407
1004
|
toMonthlyAmount,
|
|
408
1005
|
toYearlyAmount,
|
|
409
1006
|
truncate
|