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