@happyvertical/smrt-projects 0.43.9 → 0.44.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/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +71 -3
- package/dist/services/service-evidence-service.d.ts.map +1 -1
- package/dist/services/subscription-commercial-resolver.d.ts +2 -3
- package/dist/services/subscription-commercial-resolver.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +47 -5
- package/dist/svelte/AssistanceLauncher.svelte +5 -0
- package/dist/svelte/AssistanceLauncher.svelte.d.ts +5 -0
- package/dist/svelte/AssistanceLauncher.svelte.d.ts.map +1 -1
- package/dist/svelte/DeliveryStatus.svelte +1 -0
- package/dist/svelte/DeliveryStatus.svelte.d.ts +1 -0
- package/dist/svelte/DeliveryStatus.svelte.d.ts.map +1 -1
- package/dist/svelte/DevelopmentBoard.svelte +3 -0
- package/dist/svelte/DevelopmentBoard.svelte.d.ts +3 -0
- package/dist/svelte/DevelopmentBoard.svelte.d.ts.map +1 -1
- package/dist/svelte/DevelopmentRequestDetail.svelte +2 -0
- package/dist/svelte/DevelopmentRequestDetail.svelte.d.ts +2 -0
- package/dist/svelte/DevelopmentRequestDetail.svelte.d.ts.map +1 -1
- package/dist/svelte/PreviewApprovalPanel.svelte +3 -0
- package/dist/svelte/PreviewApprovalPanel.svelte.d.ts +3 -0
- package/dist/svelte/PreviewApprovalPanel.svelte.d.ts.map +1 -1
- package/dist/svelte/ServiceEvidenceList.svelte +1 -0
- package/dist/svelte/ServiceEvidenceList.svelte.d.ts +1 -0
- package/dist/svelte/ServiceEvidenceList.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ApprovalActions.svelte +9 -0
- package/dist/svelte/components/ApprovalActions.svelte.d.ts +9 -0
- package/dist/svelte/components/ApprovalActions.svelte.d.ts.map +1 -1
- package/dist/svelte/components/BulkActions.svelte +7 -0
- package/dist/svelte/components/BulkActions.svelte.d.ts +7 -0
- package/dist/svelte/components/BulkActions.svelte.d.ts.map +1 -1
- package/dist/svelte/components/DevelopmentRequestForm.svelte +2 -0
- package/dist/svelte/components/DevelopmentRequestForm.svelte.d.ts +2 -0
- package/dist/svelte/components/DevelopmentRequestForm.svelte.d.ts.map +1 -1
- package/dist/svelte/components/DevelopmentRequestList.svelte +3 -0
- package/dist/svelte/components/DevelopmentRequestList.svelte.d.ts +3 -0
- package/dist/svelte/components/DevelopmentRequestList.svelte.d.ts.map +1 -1
- package/dist/svelte/components/DurationDisplay.svelte +16 -3
- package/dist/svelte/components/DurationDisplay.svelte.d.ts +9 -0
- package/dist/svelte/components/DurationDisplay.svelte.d.ts.map +1 -1
- package/dist/svelte/components/RejectDialog.svelte +10 -0
- package/dist/svelte/components/RejectDialog.svelte.d.ts +10 -0
- package/dist/svelte/components/RejectDialog.svelte.d.ts.map +1 -1
- package/dist/svelte/components/TimeEntryCard.svelte +8 -0
- package/dist/svelte/components/TimeEntryCard.svelte.d.ts +8 -0
- package/dist/svelte/components/TimeEntryCard.svelte.d.ts.map +1 -1
- package/dist/svelte/components/TimeEntryList.svelte +7 -0
- package/dist/svelte/components/TimeEntryList.svelte.d.ts +7 -0
- package/dist/svelte/components/TimeEntryList.svelte.d.ts.map +1 -1
- package/dist/svelte/components/TimeSummary.svelte +11 -0
- package/dist/svelte/components/TimeSummary.svelte.d.ts +11 -0
- package/dist/svelte/components/TimeSummary.svelte.d.ts.map +1 -1
- package/dist/svelte/components/__tests__/DurationDisplay.test.js +34 -0
- package/package.json +12 -11
|
@@ -8,9 +8,18 @@ import { formatHoursHHMM } from './utils.js';
|
|
|
8
8
|
|
|
9
9
|
/** Props for DurationDisplay component */
|
|
10
10
|
export interface Props {
|
|
11
|
+
/** Duration in hours to display. */
|
|
11
12
|
hours: number;
|
|
13
|
+
/** Format duration as decimal (8.5) or hours:minutes (8:30). */
|
|
12
14
|
format?: 'decimal' | 'hhmm';
|
|
15
|
+
/** Sets the font size of the duration display. */
|
|
13
16
|
size?: 'sm' | 'md' | 'lg';
|
|
17
|
+
/**
|
|
18
|
+
* Renders the `h` unit after a `decimal` value; set `false` for a bare
|
|
19
|
+
* number, such as in a column whose header already names the unit. An
|
|
20
|
+
* `hhmm` value spells its own unit in the `8:30` shape and never appends a
|
|
21
|
+
* separate one, so this prop does not affect that format.
|
|
22
|
+
*/
|
|
14
23
|
showLabel?: boolean;
|
|
15
24
|
}
|
|
16
25
|
|
|
@@ -18,19 +27,23 @@ let {
|
|
|
18
27
|
hours,
|
|
19
28
|
format = 'decimal',
|
|
20
29
|
size = 'md',
|
|
21
|
-
showLabel =
|
|
30
|
+
showLabel = true,
|
|
22
31
|
}: Props = $props();
|
|
23
32
|
|
|
24
33
|
// $derived creates a reactive value, not a function - no wrapper or parentheses needed
|
|
25
34
|
const formattedValue = $derived(
|
|
26
35
|
format === 'hhmm' ? formatHoursHHMM(hours) : hours.toFixed(1),
|
|
27
36
|
);
|
|
37
|
+
|
|
38
|
+
// Only the decimal form needs a unit appended: `8:30` already reads as hours
|
|
39
|
+
// and minutes. That makes `h` the one unit `showLabel` has to gate.
|
|
40
|
+
const unit = $derived(format === 'hhmm' ? '' : 'h');
|
|
28
41
|
</script>
|
|
29
42
|
|
|
30
43
|
<span class="duration" class:sm={size === 'sm'} class:lg={size === 'lg'}>
|
|
31
44
|
<span class="value">{formattedValue}</span>
|
|
32
|
-
{#if showLabel
|
|
33
|
-
<span class="unit">{
|
|
45
|
+
{#if showLabel && unit}
|
|
46
|
+
<span class="unit">{unit}</span>
|
|
34
47
|
{/if}
|
|
35
48
|
</span>
|
|
36
49
|
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
/** Props for DurationDisplay component */
|
|
2
2
|
export interface Props {
|
|
3
|
+
/** Duration in hours to display. */
|
|
3
4
|
hours: number;
|
|
5
|
+
/** Format duration as decimal (8.5) or hours:minutes (8:30). */
|
|
4
6
|
format?: 'decimal' | 'hhmm';
|
|
7
|
+
/** Sets the font size of the duration display. */
|
|
5
8
|
size?: 'sm' | 'md' | 'lg';
|
|
9
|
+
/**
|
|
10
|
+
* Renders the `h` unit after a `decimal` value; set `false` for a bare
|
|
11
|
+
* number, such as in a column whose header already names the unit. An
|
|
12
|
+
* `hhmm` value spells its own unit in the `8:30` shape and never appends a
|
|
13
|
+
* separate one, so this prop does not affect that format.
|
|
14
|
+
*/
|
|
6
15
|
showLabel?: boolean;
|
|
7
16
|
}
|
|
8
17
|
declare const DurationDisplay: import("svelte").Component<Props, {}, "">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DurationDisplay.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/DurationDisplay.svelte.ts"],"names":[],"mappings":"AAUA,0CAA0C;AAC1C,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC5B,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"DurationDisplay.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/DurationDisplay.svelte.ts"],"names":[],"mappings":"AAUA,0CAA0C;AAC1C,MAAM,WAAW,KAAK;IACpB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC5B,kDAAkD;IAClD,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAmCD,QAAA,MAAM,eAAe,2CAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
|
|
@@ -12,15 +12,25 @@ const { t } = useI18n();
|
|
|
12
12
|
|
|
13
13
|
/** Props for RejectDialog component */
|
|
14
14
|
export interface Props {
|
|
15
|
+
/** Controls whether the dialog is displayed. */
|
|
15
16
|
open: boolean;
|
|
17
|
+
/** Dialog heading text. */
|
|
16
18
|
title?: string;
|
|
19
|
+
/** Instructions displayed above the reason input. */
|
|
17
20
|
message?: string;
|
|
21
|
+
/** Label for the confirm button. */
|
|
18
22
|
confirmLabel?: string;
|
|
23
|
+
/** Label for the cancel button. */
|
|
19
24
|
cancelLabel?: string;
|
|
25
|
+
/** Placeholder text for the reason textarea. */
|
|
20
26
|
placeholder?: string;
|
|
27
|
+
/** Requires the user to enter a reason before confirming. */
|
|
21
28
|
required?: boolean;
|
|
29
|
+
/** Disables the dialog controls during processing. */
|
|
22
30
|
loading?: boolean;
|
|
31
|
+
/** Invoked when the user confirms the rejection with a reason. */
|
|
23
32
|
onconfirm: (reason: string) => void;
|
|
33
|
+
/** Invoked when the user cancels or closes the dialog. */
|
|
24
34
|
oncancel: () => void;
|
|
25
35
|
}
|
|
26
36
|
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
/** Props for RejectDialog component */
|
|
2
2
|
export interface Props {
|
|
3
|
+
/** Controls whether the dialog is displayed. */
|
|
3
4
|
open: boolean;
|
|
5
|
+
/** Dialog heading text. */
|
|
4
6
|
title?: string;
|
|
7
|
+
/** Instructions displayed above the reason input. */
|
|
5
8
|
message?: string;
|
|
9
|
+
/** Label for the confirm button. */
|
|
6
10
|
confirmLabel?: string;
|
|
11
|
+
/** Label for the cancel button. */
|
|
7
12
|
cancelLabel?: string;
|
|
13
|
+
/** Placeholder text for the reason textarea. */
|
|
8
14
|
placeholder?: string;
|
|
15
|
+
/** Requires the user to enter a reason before confirming. */
|
|
9
16
|
required?: boolean;
|
|
17
|
+
/** Disables the dialog controls during processing. */
|
|
10
18
|
loading?: boolean;
|
|
19
|
+
/** Invoked when the user confirms the rejection with a reason. */
|
|
11
20
|
onconfirm: (reason: string) => void;
|
|
21
|
+
/** Invoked when the user cancels or closes the dialog. */
|
|
12
22
|
oncancel: () => void;
|
|
13
23
|
}
|
|
14
24
|
declare const RejectDialog: import("svelte").Component<Props, {}, "">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RejectDialog.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/RejectDialog.svelte.ts"],"names":[],"mappings":"AAYA,uCAAuC;AACvC,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AA4FD,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"RejectDialog.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/RejectDialog.svelte.ts"],"names":[],"mappings":"AAYA,uCAAuC;AACvC,MAAM,WAAW,KAAK;IACpB,gDAAgD;IAChD,IAAI,EAAE,OAAO,CAAC;IACd,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AA4FD,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -18,13 +18,21 @@ import {
|
|
|
18
18
|
|
|
19
19
|
/** Props for TimeEntryCard component */
|
|
20
20
|
export interface Props {
|
|
21
|
+
/** Time entry data to display. */
|
|
21
22
|
entry: TimeEntry;
|
|
23
|
+
/** URL to navigate to when the card is clicked. */
|
|
22
24
|
href?: string;
|
|
25
|
+
/** Invoked when the card content is clicked. */
|
|
23
26
|
onclick?: () => void;
|
|
27
|
+
/** Shows a checkbox for selecting the entry. */
|
|
24
28
|
selectable?: boolean;
|
|
29
|
+
/** Indicates whether the entry is selected. */
|
|
25
30
|
selected?: boolean;
|
|
31
|
+
/** Invoked when the selection checkbox is toggled. */
|
|
26
32
|
onselect?: (id: string, selected: boolean) => void;
|
|
33
|
+
/** Currency code for formatting hourly rates and amounts. */
|
|
27
34
|
currency?: Currency;
|
|
35
|
+
/** Renders action buttons on the right side of the card. */
|
|
28
36
|
actions?: Snippet;
|
|
29
37
|
}
|
|
30
38
|
|
|
@@ -2,13 +2,21 @@ import type { Snippet } from 'svelte';
|
|
|
2
2
|
import { type Currency, type TimeEntry } from './utils.js';
|
|
3
3
|
/** Props for TimeEntryCard component */
|
|
4
4
|
export interface Props {
|
|
5
|
+
/** Time entry data to display. */
|
|
5
6
|
entry: TimeEntry;
|
|
7
|
+
/** URL to navigate to when the card is clicked. */
|
|
6
8
|
href?: string;
|
|
9
|
+
/** Invoked when the card content is clicked. */
|
|
7
10
|
onclick?: () => void;
|
|
11
|
+
/** Shows a checkbox for selecting the entry. */
|
|
8
12
|
selectable?: boolean;
|
|
13
|
+
/** Indicates whether the entry is selected. */
|
|
9
14
|
selected?: boolean;
|
|
15
|
+
/** Invoked when the selection checkbox is toggled. */
|
|
10
16
|
onselect?: (id: string, selected: boolean) => void;
|
|
17
|
+
/** Currency code for formatting hourly rates and amounts. */
|
|
11
18
|
currency?: Currency;
|
|
19
|
+
/** Renders action buttons on the right side of the card. */
|
|
12
20
|
actions?: Snippet;
|
|
13
21
|
}
|
|
14
22
|
declare const TimeEntryCard: import("svelte").Component<Props, {}, "">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeEntryCard.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/TimeEntryCard.svelte.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EACL,KAAK,QAAQ,EAKb,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAGpB,wCAAwC;AACxC,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACnD,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAoHD,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"TimeEntryCard.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/TimeEntryCard.svelte.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EACL,KAAK,QAAQ,EAKb,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAGpB,wCAAwC;AACxC,MAAM,WAAW,KAAK;IACpB,kCAAkC;IAClC,KAAK,EAAE,SAAS,CAAC;IACjB,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,gDAAgD;IAChD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACnD,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAoHD,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -19,12 +19,19 @@ const { t } = useI18n();
|
|
|
19
19
|
|
|
20
20
|
/** Props for TimeEntryList component */
|
|
21
21
|
export interface Props {
|
|
22
|
+
/** Time entries to display in the list. */
|
|
22
23
|
entries: TimeEntry[];
|
|
24
|
+
/** Shows checkboxes for selecting entries. */
|
|
23
25
|
selectable?: boolean;
|
|
26
|
+
/** Identifiers of currently selected entries. */
|
|
24
27
|
selectedIds?: string[];
|
|
28
|
+
/** Invoked when the selection changes. */
|
|
25
29
|
onselectionchange?: (ids: string[]) => void;
|
|
30
|
+
/** Message shown when the entries list is empty. */
|
|
26
31
|
emptyMessage?: string;
|
|
32
|
+
/** Base URL to construct entry detail links. */
|
|
27
33
|
baseHref?: string;
|
|
34
|
+
/** Currency code for formatting amounts. */
|
|
28
35
|
currency?: Currency;
|
|
29
36
|
/** Filter function to determine which entries can be selected */
|
|
30
37
|
canSelect?: (entry: TimeEntry) => boolean;
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import { type Currency, type TimeEntry } from './utils.js';
|
|
2
2
|
/** Props for TimeEntryList component */
|
|
3
3
|
export interface Props {
|
|
4
|
+
/** Time entries to display in the list. */
|
|
4
5
|
entries: TimeEntry[];
|
|
6
|
+
/** Shows checkboxes for selecting entries. */
|
|
5
7
|
selectable?: boolean;
|
|
8
|
+
/** Identifiers of currently selected entries. */
|
|
6
9
|
selectedIds?: string[];
|
|
10
|
+
/** Invoked when the selection changes. */
|
|
7
11
|
onselectionchange?: (ids: string[]) => void;
|
|
12
|
+
/** Message shown when the entries list is empty. */
|
|
8
13
|
emptyMessage?: string;
|
|
14
|
+
/** Base URL to construct entry detail links. */
|
|
9
15
|
baseHref?: string;
|
|
16
|
+
/** Currency code for formatting amounts. */
|
|
10
17
|
currency?: Currency;
|
|
11
18
|
/** Filter function to determine which entries can be selected */
|
|
12
19
|
canSelect?: (entry: TimeEntry) => boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeEntryList.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/TimeEntryList.svelte.ts"],"names":[],"mappings":"AASA,OAAO,EACL,KAAK,QAAQ,EAKb,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAGpB,wCAAwC;AACxC,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,iEAAiE;IACjE,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;CAC3C;AA2ID,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"TimeEntryList.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/TimeEntryList.svelte.ts"],"names":[],"mappings":"AASA,OAAO,EACL,KAAK,QAAQ,EAKb,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAGpB,wCAAwC;AACxC,MAAM,WAAW,KAAK;IACpB,2CAA2C;IAC3C,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,0CAA0C;IAC1C,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC5C,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,iEAAiE;IACjE,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;CAC3C;AA2ID,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -10,16 +10,27 @@ import { type Currency, formatCurrency, formatHours } from './utils.js';
|
|
|
10
10
|
|
|
11
11
|
/** Props for TimeSummary component */
|
|
12
12
|
export interface Props {
|
|
13
|
+
/** Total hours across all time entries. */
|
|
13
14
|
totalHours: number;
|
|
15
|
+
/** Total charged or invoiced amount. */
|
|
14
16
|
totalAmount: number;
|
|
17
|
+
/** Hours awaiting approval. */
|
|
15
18
|
pendingHours?: number;
|
|
19
|
+
/** Amount awaiting approval. */
|
|
16
20
|
pendingAmount?: number;
|
|
21
|
+
/** Hours that have been approved. */
|
|
17
22
|
approvedHours?: number;
|
|
23
|
+
/** Amount that has been approved. */
|
|
18
24
|
approvedAmount?: number;
|
|
25
|
+
/** Number of time entries included in the summary. */
|
|
19
26
|
entryCount?: number;
|
|
27
|
+
/** Currency code for formatting amounts. */
|
|
20
28
|
currency?: Currency;
|
|
29
|
+
/** Shows the pending hours and amount card when there are pending items. */
|
|
21
30
|
showPending?: boolean;
|
|
31
|
+
/** Shows the approved hours and amount card when there are approved items. */
|
|
22
32
|
showApproved?: boolean;
|
|
33
|
+
/** Arranges summary cards in a grid or flexbox layout. */
|
|
23
34
|
layout?: 'horizontal' | 'grid';
|
|
24
35
|
}
|
|
25
36
|
|
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
import { type Currency } from './utils.js';
|
|
2
2
|
/** Props for TimeSummary component */
|
|
3
3
|
export interface Props {
|
|
4
|
+
/** Total hours across all time entries. */
|
|
4
5
|
totalHours: number;
|
|
6
|
+
/** Total charged or invoiced amount. */
|
|
5
7
|
totalAmount: number;
|
|
8
|
+
/** Hours awaiting approval. */
|
|
6
9
|
pendingHours?: number;
|
|
10
|
+
/** Amount awaiting approval. */
|
|
7
11
|
pendingAmount?: number;
|
|
12
|
+
/** Hours that have been approved. */
|
|
8
13
|
approvedHours?: number;
|
|
14
|
+
/** Amount that has been approved. */
|
|
9
15
|
approvedAmount?: number;
|
|
16
|
+
/** Number of time entries included in the summary. */
|
|
10
17
|
entryCount?: number;
|
|
18
|
+
/** Currency code for formatting amounts. */
|
|
11
19
|
currency?: Currency;
|
|
20
|
+
/** Shows the pending hours and amount card when there are pending items. */
|
|
12
21
|
showPending?: boolean;
|
|
22
|
+
/** Shows the approved hours and amount card when there are approved items. */
|
|
13
23
|
showApproved?: boolean;
|
|
24
|
+
/** Arranges summary cards in a grid or flexbox layout. */
|
|
14
25
|
layout?: 'horizontal' | 'grid';
|
|
15
26
|
}
|
|
16
27
|
declare const TimeSummary: import("svelte").Component<Props, {}, "">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeSummary.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/TimeSummary.svelte.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,QAAQ,EAA+B,MAAM,YAAY,CAAC;AAGxE,sCAAsC;AACtC,MAAM,WAAW,KAAK;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;CAChC;AA6DD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"TimeSummary.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/TimeSummary.svelte.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,QAAQ,EAA+B,MAAM,YAAY,CAAC;AAGxE,sCAAsC;AACtC,MAAM,WAAW,KAAK;IACpB,2CAA2C;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gCAAgC;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;CAChC;AA6DD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|
|
@@ -14,6 +14,40 @@ describe('DurationDisplay', () => {
|
|
|
14
14
|
render(DurationDisplay, { props: { hours: 1.5, format: 'hhmm' } });
|
|
15
15
|
expect(screen.getByText('1:30')).toBeInTheDocument();
|
|
16
16
|
});
|
|
17
|
+
// #2605: `showLabel` used to be inert. `decimal` rendered `h` whatever the
|
|
18
|
+
// prop said, and `hhmm` rendered an empty `<span class="unit">` instead of a
|
|
19
|
+
// label. These pin the unit to the prop, and pin the unchanged defaults so a
|
|
20
|
+
// later change to them has to be deliberate.
|
|
21
|
+
describe('showLabel', () => {
|
|
22
|
+
it('renders the decimal unit by default', () => {
|
|
23
|
+
const { container } = render(DurationDisplay, { props: { hours: 2.5 } });
|
|
24
|
+
expect(container.querySelector('.unit')?.textContent).toBe('h');
|
|
25
|
+
});
|
|
26
|
+
it('renders the decimal unit when showLabel is set', () => {
|
|
27
|
+
const { container } = render(DurationDisplay, {
|
|
28
|
+
props: { hours: 2.5, showLabel: true },
|
|
29
|
+
});
|
|
30
|
+
expect(container.querySelector('.unit')?.textContent).toBe('h');
|
|
31
|
+
});
|
|
32
|
+
it('drops the decimal unit when showLabel is cleared', () => {
|
|
33
|
+
const { container } = render(DurationDisplay, {
|
|
34
|
+
props: { hours: 2.5, showLabel: false },
|
|
35
|
+
});
|
|
36
|
+
expect(container.querySelector('.unit')).toBeNull();
|
|
37
|
+
expect(container.textContent?.trim()).toBe('2.5');
|
|
38
|
+
});
|
|
39
|
+
it.each([
|
|
40
|
+
undefined,
|
|
41
|
+
true,
|
|
42
|
+
false,
|
|
43
|
+
])('renders no unit element in hhmm format with showLabel=%s', (showLabel) => {
|
|
44
|
+
const { container } = render(DurationDisplay, {
|
|
45
|
+
props: { hours: 1.5, format: 'hhmm', showLabel },
|
|
46
|
+
});
|
|
47
|
+
expect(container.querySelector('.unit')).toBeNull();
|
|
48
|
+
expect(container.textContent?.trim()).toBe('1:30');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
17
51
|
it('is axe-clean', async () => {
|
|
18
52
|
const { container } = render(DurationDisplay, {
|
|
19
53
|
props: { hours: 8, showLabel: true },
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-projects",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.44.0",
|
|
4
|
+
"smrtJsdoc": "strict",
|
|
4
5
|
"description": "Provider-agnostic project management models (Issues, PRs, Repositories, Projects) for SMRT framework",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"smrtRawPrimitives": "strict",
|
|
@@ -40,14 +41,14 @@
|
|
|
40
41
|
"@happyvertical/repos": "^0.89.4",
|
|
41
42
|
"@happyvertical/sql": "^0.89.4",
|
|
42
43
|
"@happyvertical/utils": "^0.89.4",
|
|
43
|
-
"@happyvertical/smrt-config": "0.
|
|
44
|
-
"@happyvertical/smrt-
|
|
45
|
-
"@happyvertical/smrt-
|
|
46
|
-
"@happyvertical/smrt-
|
|
47
|
-
"@happyvertical/smrt-
|
|
48
|
-
"@happyvertical/smrt-
|
|
49
|
-
"@happyvertical/smrt-ui": "0.
|
|
50
|
-
"@happyvertical/smrt-types": "0.
|
|
44
|
+
"@happyvertical/smrt-config": "0.44.0",
|
|
45
|
+
"@happyvertical/smrt-core": "0.44.0",
|
|
46
|
+
"@happyvertical/smrt-prompts": "0.44.0",
|
|
47
|
+
"@happyvertical/smrt-subscriptions": "0.44.0",
|
|
48
|
+
"@happyvertical/smrt-tenancy": "0.44.0",
|
|
49
|
+
"@happyvertical/smrt-svelte": "0.44.0",
|
|
50
|
+
"@happyvertical/smrt-ui": "0.44.0",
|
|
51
|
+
"@happyvertical/smrt-types": "0.44.0"
|
|
51
52
|
},
|
|
52
53
|
"peerDependencies": {
|
|
53
54
|
"svelte": "^5.56.4"
|
|
@@ -67,8 +68,8 @@
|
|
|
67
68
|
"typescript": "5.9.3",
|
|
68
69
|
"vite": "8.1.4",
|
|
69
70
|
"vitest": "4.1.10",
|
|
70
|
-
"@happyvertical/smrt-
|
|
71
|
-
"@happyvertical/smrt-
|
|
71
|
+
"@happyvertical/smrt-vitest": "0.44.0",
|
|
72
|
+
"@happyvertical/smrt-cli": "0.44.0"
|
|
72
73
|
},
|
|
73
74
|
"keywords": [
|
|
74
75
|
"ai",
|