@nightkatana/kronosys-app 1.0.0-beta.13 → 1.0.0-beta.14

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 (55) hide show
  1. package/app/globals.css +98 -0
  2. package/app/guide/page.tsx +59 -15
  3. package/app/implementation/page.tsx +317 -0
  4. package/app/layout.tsx +11 -3
  5. package/app/licenses/page.tsx +97 -37
  6. package/app/page.tsx +578 -192
  7. package/app/reporting/page.tsx +1073 -203
  8. package/app/settings/page.tsx +101 -16
  9. package/components/KronosysPayloadProvider.tsx +2 -0
  10. package/components/RouteTransition.tsx +18 -0
  11. package/components/dashboard/AppShellCommandCenterPlaceholder.tsx +17 -0
  12. package/components/dashboard/AppShellHeaderSessionMeta.tsx +210 -0
  13. package/components/dashboard/AppShellRouteNav.tsx +237 -48
  14. package/components/dashboard/DashboardSimpleModal.tsx +168 -25
  15. package/components/dashboard/GlobalPauseConfirmModal.tsx +183 -0
  16. package/components/dashboard/KronosysDatetimePopoverField.tsx +128 -119
  17. package/components/dashboard/NewSessionScopeModal.tsx +13 -0
  18. package/components/dashboard/SelectedSessionSidebarBlock.tsx +333 -116
  19. package/components/dashboard/SessionListPanel.tsx +279 -43
  20. package/components/dashboard/SettingsTagsProjectsSection.tsx +655 -239
  21. package/components/dashboard/SettingsTaskTemplatesSection.tsx +314 -0
  22. package/components/dashboard/TaskFocusPanel.tsx +602 -373
  23. package/components/dashboard/TaskSessionLiveCard.tsx +341 -115
  24. package/components/dashboard/TaskTimelineGanttModal.tsx +557 -0
  25. package/components/dashboard/taskFieldStyles.ts +3 -2
  26. package/lib/appShellHeaderClasses.ts +13 -0
  27. package/lib/dashboardCopy.ts +326 -81
  28. package/lib/dashboardQuickSearch.ts +54 -2
  29. package/lib/formatSessionNameTemplate.test.ts +53 -0
  30. package/lib/formatSessionNameTemplate.ts +141 -0
  31. package/lib/generatedUserChangelog.ts +9 -0
  32. package/lib/globalPausePreview.test.ts +170 -0
  33. package/lib/globalPausePreview.ts +292 -0
  34. package/lib/implementationNotes.ts +647 -0
  35. package/lib/reportingAggregate.test.ts +31 -4
  36. package/lib/reportingAggregate.ts +72 -0
  37. package/lib/reportingMetricHelp.ts +8 -0
  38. package/lib/reportingStrings.ts +28 -3
  39. package/lib/reportingTagWeekBreakdown.test.ts +4 -3
  40. package/lib/sessionTaskSidebarStats.test.ts +27 -1
  41. package/lib/sessionTaskSidebarStats.ts +124 -9
  42. package/lib/settingsCopy.ts +105 -0
  43. package/lib/taskTemplateDraft.test.ts +52 -0
  44. package/lib/taskTemplateDraft.ts +121 -0
  45. package/lib/taskTimelineGantt.test.ts +50 -0
  46. package/lib/taskTimelineGantt.ts +165 -0
  47. package/lib/userGuideCopy.ts +44 -28
  48. package/next-env.d.ts +1 -1
  49. package/package.json +2 -2
  50. package/server/actionDispatch.test.ts +184 -0
  51. package/server/actionDispatch.ts +453 -6
  52. package/server/actionTaskSession.ts +58 -11
  53. package/server/defaultCfg.ts +5 -0
  54. package/server/sessionWallHydrate.ts +13 -0
  55. package/components/dashboard/IssuePickerModal.tsx +0 -168
@@ -8,8 +8,16 @@ import { ScrollToTopFab } from "@/components/dashboard/ScrollToTopFab";
8
8
  import { ThemeToggle } from "@/components/dashboard/ThemeToggle";
9
9
  import { PageRefreshButton } from "@/components/dashboard/PageRefreshButton";
10
10
  import { AppShellRouteNav } from "@/components/dashboard/AppShellRouteNav";
11
+ import { useKronosysPayload } from "@/components/KronosysPayloadProvider";
11
12
  import { dashboardStrings, type Lang } from "@/lib/dashboardCopy";
12
- import { appShellHeaderClassName, appShellHeaderToolRowClassName } from "@/lib/appShellHeaderClasses";
13
+ import {
14
+ appShellHeaderClassName,
15
+ appShellHeaderTitleMetaRowClassName,
16
+ appShellHeaderToolbarClassName,
17
+ } from "@/lib/appShellHeaderClasses";
18
+ import { AppShellCommandCenterPlaceholder } from "@/components/dashboard/AppShellCommandCenterPlaceholder";
19
+ import { AppShellHeaderSessionMeta } from "@/components/dashboard/AppShellHeaderSessionMeta";
20
+ import { LanguageMenu } from "@/components/dashboard/LanguageMenu";
13
21
  import { reportingNav } from "@/lib/reportingStrings";
14
22
  import {
15
23
  DASHBOARD_DEV_THIRD_PARTY,
@@ -23,6 +31,7 @@ import { withDashboardSessionParam } from "@/lib/dashboardSessionNav";
23
31
  function LicensesBody() {
24
32
  const router = useRouter();
25
33
  const searchParams = useSearchParams();
34
+ const { payload } = useKronosysPayload();
26
35
  const dashboardSessionNavId = searchParams.get("session");
27
36
  const lang: LicensesLang = searchParams.get("lang") === "en" ? "en" : "fr";
28
37
  const c = useMemo(() => licensesCopy(lang), [lang]);
@@ -32,7 +41,7 @@ function LicensesBody() {
32
41
  return (
33
42
  <div className="min-h-screen bg-zinc-100 text-zinc-900 dark:bg-zinc-900 dark:text-zinc-100">
34
43
  <header className={appShellHeaderClassName}>
35
- <div className={appShellHeaderToolRowClassName}>
44
+ <div className={appShellHeaderTitleMetaRowClassName}>
36
45
  <div className="flex min-w-0 flex-col gap-1">
37
46
  <div className="flex min-w-0 flex-wrap items-baseline gap-x-2 gap-y-0.5">
38
47
  <Link
@@ -42,7 +51,9 @@ function LicensesBody() {
42
51
  Kronosys
43
52
  </Link>
44
53
  <span className="text-zinc-400 dark:text-zinc-600">/</span>
45
- <span className="text-lg font-medium text-zinc-700 dark:text-zinc-300">{c.title}</span>
54
+ <span className="text-lg font-medium text-zinc-700 dark:text-zinc-300">
55
+ {c.title}
56
+ </span>
46
57
  </div>
47
58
  <p className="flex flex-wrap items-center gap-x-2 text-xs font-medium leading-snug text-zinc-500 dark:text-zinc-400">
48
59
  <span>{dt.brandTagline}</span>
@@ -52,14 +63,19 @@ function LicensesBody() {
52
63
  <AppVersionStamp ariaLabelTemplate={dt.appVersionAriaLabel} />
53
64
  </p>
54
65
  </div>
55
- <div className="flex flex-wrap items-center gap-1.5 text-sm">
66
+ <AppShellHeaderSessionMeta payload={payload} dt={dt} />
67
+ </div>
68
+ <div className="flex w-full justify-end">
69
+ <div className={appShellHeaderToolbarClassName}>
70
+ <AppShellCommandCenterPlaceholder />
56
71
  <AppShellRouteNav
57
72
  current="licenses"
58
73
  labels={{ ...nav, licenses: c.title }}
59
74
  navAriaLabel={dt.appShellRouteNavAria}
60
75
  dashboardSessionId={dashboardSessionNavId}
76
+ reserveGlobalPauseSlot
61
77
  />
62
- <ThemeToggle lang={lang} />
78
+ <ThemeToggle lang={lang as Lang} />
63
79
  <PageRefreshButton
64
80
  title={dt.pageRefreshTitle}
65
81
  ariaLabel={dt.pageRefreshAriaLabel}
@@ -72,21 +88,28 @@ function LicensesBody() {
72
88
  router.refresh();
73
89
  }}
74
90
  />
75
- <span className="hidden h-4 w-px bg-zinc-300 dark:bg-zinc-700 sm:inline-block" aria-hidden />
76
- <Link
77
- href={withDashboardSessionParam("/licenses", dashboardSessionNavId)}
78
- className={`rounded-md px-3 py-1.5 ${lang === "fr" ? "border border-violet-600/60 bg-violet-950/40 text-violet-100" : "border border-zinc-700 bg-zinc-900 text-zinc-200 hover:border-zinc-500"}`}
79
- hrefLang="fr"
80
- >
81
- Français
82
- </Link>
83
- <Link
84
- href={withDashboardSessionParam("/licenses?lang=en", dashboardSessionNavId)}
85
- className={`rounded-md px-3 py-1.5 ${lang === "en" ? "border border-violet-600/60 bg-violet-950/40 text-violet-100" : "border border-zinc-700 bg-zinc-900 text-zinc-200 hover:border-zinc-500"}`}
86
- hrefLang="en"
87
- >
88
- English
89
- </Link>
91
+ <LanguageMenu
92
+ lang={lang as Lang}
93
+ labelEn="English"
94
+ labelFr="Français"
95
+ menuHeading={lang === "fr" ? "Langue" : "Language"}
96
+ triggerAriaLabel={
97
+ lang === "fr" ? "Langue de l’interface" : "Interface language"
98
+ }
99
+ onSelect={(next) => {
100
+ const path =
101
+ next === "en"
102
+ ? withDashboardSessionParam(
103
+ "/licenses?lang=en",
104
+ dashboardSessionNavId,
105
+ )
106
+ : withDashboardSessionParam(
107
+ "/licenses",
108
+ dashboardSessionNavId,
109
+ );
110
+ router.push(path);
111
+ }}
112
+ />
90
113
  </div>
91
114
  </div>
92
115
  </header>
@@ -95,13 +118,22 @@ function LicensesBody() {
95
118
  <p className="text-sm leading-relaxed text-zinc-400">{c.intro}</p>
96
119
 
97
120
  <section className="mt-10" aria-labelledby="lic-kronosys-product">
98
- <h2 id="lic-kronosys-product" className="text-base font-semibold text-zinc-200">
121
+ <h2
122
+ id="lic-kronosys-product"
123
+ className="text-base font-semibold text-zinc-200"
124
+ >
99
125
  {c.kronosysSectionTitle}
100
126
  </h2>
101
- <p className="mt-2 text-sm leading-relaxed text-zinc-400">{c.kronosysProduct}</p>
102
- <p className="mt-2 text-sm font-medium text-zinc-300">{c.copyrightLine}</p>
127
+ <p className="mt-2 text-sm leading-relaxed text-zinc-400">
128
+ {c.kronosysProduct}
129
+ </p>
130
+ <p className="mt-2 text-sm font-medium text-zinc-300">
131
+ {c.copyrightLine}
132
+ </p>
103
133
 
104
- <h3 className="mt-6 text-sm font-semibold uppercase tracking-wide text-zinc-500">{c.mitHeading}</h3>
134
+ <h3 className="mt-6 text-sm font-semibold uppercase tracking-wide text-zinc-500">
135
+ {c.mitHeading}
136
+ </h3>
105
137
  <pre className="mt-3 overflow-x-auto rounded-lg border border-zinc-800 bg-zinc-900/60 p-4 text-xs leading-relaxed whitespace-pre-wrap text-zinc-300">
106
138
  {KRONOSYS_MIT_LICENSE_BODY}
107
139
  </pre>
@@ -115,16 +147,27 @@ function LicensesBody() {
115
147
  <table className="w-full min-w-[20rem] text-left text-sm">
116
148
  <thead className="border-b border-zinc-800 bg-zinc-900/50 text-xs uppercase text-zinc-500">
117
149
  <tr>
118
- <th className="px-3 py-2 font-medium">{c.thirdPartyColName}</th>
119
- <th className="px-3 py-2 font-medium">{c.thirdPartyColLicense}</th>
120
- <th className="px-3 py-2 font-medium">{c.thirdPartyColLink}</th>
150
+ <th className="px-3 py-2 font-medium">
151
+ {c.thirdPartyColName}
152
+ </th>
153
+ <th className="px-3 py-2 font-medium">
154
+ {c.thirdPartyColLicense}
155
+ </th>
156
+ <th className="px-3 py-2 font-medium">
157
+ {c.thirdPartyColLink}
158
+ </th>
121
159
  </tr>
122
160
  </thead>
123
161
  <tbody>
124
162
  {DASHBOARD_THIRD_PARTY.map((row) => (
125
- <tr key={row.name} className="border-b border-zinc-800/80 last:border-0">
163
+ <tr
164
+ key={row.name}
165
+ className="border-b border-zinc-800/80 last:border-0"
166
+ >
126
167
  <td className="px-3 py-2.5 text-zinc-200">{row.name}</td>
127
- <td className="px-3 py-2.5 font-mono text-xs text-zinc-400">{row.license}</td>
168
+ <td className="px-3 py-2.5 font-mono text-xs text-zinc-400">
169
+ {row.license}
170
+ </td>
128
171
  <td className="px-3 py-2.5">
129
172
  <a
130
173
  href={row.url}
@@ -150,16 +193,27 @@ function LicensesBody() {
150
193
  <table className="w-full min-w-[20rem] text-left text-sm">
151
194
  <thead className="border-b border-zinc-800 bg-zinc-900/50 text-xs uppercase text-zinc-500">
152
195
  <tr>
153
- <th className="px-3 py-2 font-medium">{c.thirdPartyColName}</th>
154
- <th className="px-3 py-2 font-medium">{c.thirdPartyColLicense}</th>
155
- <th className="px-3 py-2 font-medium">{c.thirdPartyColLink}</th>
196
+ <th className="px-3 py-2 font-medium">
197
+ {c.thirdPartyColName}
198
+ </th>
199
+ <th className="px-3 py-2 font-medium">
200
+ {c.thirdPartyColLicense}
201
+ </th>
202
+ <th className="px-3 py-2 font-medium">
203
+ {c.thirdPartyColLink}
204
+ </th>
156
205
  </tr>
157
206
  </thead>
158
207
  <tbody>
159
208
  {DASHBOARD_DEV_THIRD_PARTY.map((row) => (
160
- <tr key={row.name} className="border-b border-zinc-800/80 last:border-0">
209
+ <tr
210
+ key={row.name}
211
+ className="border-b border-zinc-800/80 last:border-0"
212
+ >
161
213
  <td className="px-3 py-2.5 text-zinc-200">{row.name}</td>
162
- <td className="px-3 py-2.5 font-mono text-xs text-zinc-400">{row.license}</td>
214
+ <td className="px-3 py-2.5 font-mono text-xs text-zinc-400">
215
+ {row.license}
216
+ </td>
163
217
  <td className="px-3 py-2.5">
164
218
  <a
165
219
  href={row.url}
@@ -181,7 +235,9 @@ function LicensesBody() {
181
235
  <h2 id="lic-fonts" className="text-base font-semibold text-zinc-200">
182
236
  {c.fontsSectionTitle}
183
237
  </h2>
184
- <p className="mt-2 text-sm leading-relaxed text-zinc-400">{c.fontsBody}</p>
238
+ <p className="mt-2 text-sm leading-relaxed text-zinc-400">
239
+ {c.fontsBody}
240
+ </p>
185
241
  <ul className="mt-3 list-inside list-disc text-sm text-zinc-400">
186
242
  <li>
187
243
  <a
@@ -220,13 +276,17 @@ function LicensesBody() {
220
276
  <h2 id="lic-ext" className="text-base font-semibold text-zinc-200">
221
277
  {c.extensionSectionTitle}
222
278
  </h2>
223
- <p className="mt-2 text-sm leading-relaxed text-zinc-400">{c.extensionNote}</p>
279
+ <p className="mt-2 text-sm leading-relaxed text-zinc-400">
280
+ {c.extensionNote}
281
+ </p>
224
282
  </section>
225
283
 
226
284
  <p className="mt-8 text-xs text-zinc-600">{c.disclaimer}</p>
227
285
  </main>
228
286
 
229
- <ScrollToTopFab ariaLabel={lang === "fr" ? "Retour en haut de la page" : "Back to top"} />
287
+ <ScrollToTopFab
288
+ ariaLabel={lang === "fr" ? "Retour en haut de la page" : "Back to top"}
289
+ />
230
290
  </div>
231
291
  );
232
292
  }