@dative-gpi/foundation-shared-components 1.1.15 → 1.1.17
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.
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<FSBaseField
|
|
3
|
+
:description="$props.description"
|
|
4
|
+
:hideHeader="$props.hideHeader"
|
|
5
|
+
:required="$props.required"
|
|
6
|
+
:disabled="$props.disabled"
|
|
7
|
+
:label="$props.label"
|
|
8
|
+
:messages="messages"
|
|
9
|
+
>
|
|
10
|
+
<FSRow
|
|
11
|
+
:wrap="false"
|
|
12
|
+
align="center-left"
|
|
13
|
+
>
|
|
14
|
+
<FSNumberField
|
|
15
|
+
suffix="h"
|
|
16
|
+
:hideHeader="true"
|
|
17
|
+
:modelValue="innerHours"
|
|
18
|
+
:disabled="$props.disabled"
|
|
19
|
+
:rules="[() => messages.length === 0 || '']"
|
|
20
|
+
@update:modelValue="onChangeHours"
|
|
21
|
+
/>
|
|
22
|
+
<FSSpan>:</FSSpan>
|
|
23
|
+
<FSNumberField
|
|
24
|
+
suffix="min"
|
|
25
|
+
:hideHeader="true"
|
|
26
|
+
:disabled="$props.disabled"
|
|
27
|
+
:rules="[() => messages.length === 0 || '']"
|
|
28
|
+
:modelValue="innerMinutes"
|
|
29
|
+
@update:modelValue="onChangeMinutes"
|
|
30
|
+
/>
|
|
31
|
+
</FSRow>
|
|
32
|
+
</FSBaseField>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script lang="ts">
|
|
36
|
+
import { computed, defineComponent, type PropType, ref, watch } from "vue";
|
|
37
|
+
|
|
38
|
+
import { NumberRules } from "@dative-gpi/foundation-shared-components/models";
|
|
39
|
+
import { useRules } from "@dative-gpi/foundation-shared-components/composables";
|
|
40
|
+
|
|
41
|
+
import FSNumberField from "./FSNumberField.vue";
|
|
42
|
+
import FSBaseField from "./FSBaseField.vue";
|
|
43
|
+
import FSSpan from "../FSSpan.vue";
|
|
44
|
+
import FSRow from "../FSRow.vue";
|
|
45
|
+
|
|
46
|
+
export default defineComponent({
|
|
47
|
+
name: "FSDurationField",
|
|
48
|
+
components: {
|
|
49
|
+
FSNumberField,
|
|
50
|
+
FSBaseField,
|
|
51
|
+
FSSpan,
|
|
52
|
+
FSRow
|
|
53
|
+
},
|
|
54
|
+
props: {
|
|
55
|
+
label: {
|
|
56
|
+
type: String as PropType<string | null>,
|
|
57
|
+
required: false,
|
|
58
|
+
default: null
|
|
59
|
+
},
|
|
60
|
+
description: {
|
|
61
|
+
type: String as PropType<string | null>,
|
|
62
|
+
required: false,
|
|
63
|
+
default: null
|
|
64
|
+
},
|
|
65
|
+
modelValue: {
|
|
66
|
+
type: Number as PropType<number | null>,
|
|
67
|
+
required: false,
|
|
68
|
+
default: null
|
|
69
|
+
},
|
|
70
|
+
maxDuration: {
|
|
71
|
+
type: Number as PropType<number | null>,
|
|
72
|
+
required: false,
|
|
73
|
+
default: null
|
|
74
|
+
},
|
|
75
|
+
minDuration: {
|
|
76
|
+
type: Number as PropType<number | null>,
|
|
77
|
+
required: false,
|
|
78
|
+
default: null
|
|
79
|
+
},
|
|
80
|
+
hideHeader: {
|
|
81
|
+
type: Boolean,
|
|
82
|
+
required: false,
|
|
83
|
+
default: false
|
|
84
|
+
},
|
|
85
|
+
required: {
|
|
86
|
+
type: Boolean,
|
|
87
|
+
required: false,
|
|
88
|
+
default: false
|
|
89
|
+
},
|
|
90
|
+
rules: {
|
|
91
|
+
type: Array as PropType<any[]>,
|
|
92
|
+
required: false,
|
|
93
|
+
default: () => []
|
|
94
|
+
},
|
|
95
|
+
messages: {
|
|
96
|
+
type: Array as PropType<string[]>,
|
|
97
|
+
required: false,
|
|
98
|
+
default: null
|
|
99
|
+
},
|
|
100
|
+
disabled: {
|
|
101
|
+
type: Boolean,
|
|
102
|
+
required: false,
|
|
103
|
+
default: false
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
emits: ["update:modelValue"],
|
|
107
|
+
setup(props, { emit }) {
|
|
108
|
+
const { getMessages } = useRules();
|
|
109
|
+
const MS_PER_MINUTE = 60 * 1000;
|
|
110
|
+
const MS_PER_HOUR = 60 * MS_PER_MINUTE;
|
|
111
|
+
|
|
112
|
+
const innerHours = ref<number | null>(null);
|
|
113
|
+
const innerMinutes = ref<number | null>(null);
|
|
114
|
+
|
|
115
|
+
const durationRules = computed(() => {
|
|
116
|
+
const rules: any[] = [...props.rules];
|
|
117
|
+
if (props.required) {
|
|
118
|
+
rules.push(NumberRules.required());
|
|
119
|
+
}
|
|
120
|
+
if (props.minDuration != null) {
|
|
121
|
+
const minHours = Math.floor(props.minDuration / MS_PER_HOUR);
|
|
122
|
+
const minMinutes = Math.floor((props.minDuration % MS_PER_HOUR) / MS_PER_MINUTE);
|
|
123
|
+
const label = minHours > 0 ? `${minHours}h${minMinutes.toString().padStart(2, '0')}` : `${minMinutes}min`;
|
|
124
|
+
rules.push((v: any) => (v != null && v >= props.minDuration!) || `Min. ${label}`);
|
|
125
|
+
}
|
|
126
|
+
if (props.maxDuration != null) {
|
|
127
|
+
const maxHours = Math.floor(props.maxDuration / MS_PER_HOUR);
|
|
128
|
+
const maxMinutes = Math.floor((props.maxDuration % MS_PER_HOUR) / MS_PER_MINUTE);
|
|
129
|
+
const label = maxHours > 0 ? `${maxHours}h${maxMinutes.toString().padStart(2, '0')}` : `${maxMinutes}min`;
|
|
130
|
+
rules.push((v: any) => (v != null && v <= props.maxDuration!) || `Max. ${label}`);
|
|
131
|
+
}
|
|
132
|
+
return rules;
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const messages = computed((): string[] => props.messages ?? getMessages(props.modelValue, durationRules.value));
|
|
136
|
+
|
|
137
|
+
const reset = (): void => {
|
|
138
|
+
if (props.modelValue == null) {
|
|
139
|
+
innerHours.value = null;
|
|
140
|
+
innerMinutes.value = null;
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
innerHours.value = Math.floor(props.modelValue / MS_PER_HOUR);
|
|
144
|
+
innerMinutes.value = Math.floor((props.modelValue % MS_PER_HOUR) / MS_PER_MINUTE);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const emitValue = (): void => {
|
|
148
|
+
const hours = innerHours.value ?? 0;
|
|
149
|
+
const minutes = innerMinutes.value ?? 0;
|
|
150
|
+
emit("update:modelValue", (hours * MS_PER_HOUR) + (minutes * MS_PER_MINUTE));
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const onChangeHours = (value: number | null): void => {
|
|
154
|
+
innerHours.value = value;
|
|
155
|
+
emitValue();
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const onChangeMinutes = (value: number | null): void => {
|
|
159
|
+
value = Math.min(59, Math.max(0, value ?? 0));
|
|
160
|
+
innerMinutes.value = value;
|
|
161
|
+
emitValue();
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
watch(() => props.modelValue, () => {
|
|
165
|
+
const currentHours = innerHours.value ?? 0;
|
|
166
|
+
const currentMinutes = innerMinutes.value ?? 0;
|
|
167
|
+
const currentTotal = (currentHours * MS_PER_HOUR) + (currentMinutes * MS_PER_MINUTE);
|
|
168
|
+
if (currentTotal !== (props.modelValue ?? 0)) {
|
|
169
|
+
reset();
|
|
170
|
+
}
|
|
171
|
+
}, { immediate: true });
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
NumberRules,
|
|
175
|
+
innerHours,
|
|
176
|
+
innerMinutes,
|
|
177
|
+
durationRules,
|
|
178
|
+
messages,
|
|
179
|
+
onChangeHours,
|
|
180
|
+
onChangeMinutes
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
</script>
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"url": "https://github.com/Dative-GPI/foundation-shared-ui.git"
|
|
5
5
|
},
|
|
6
6
|
"sideEffects": false,
|
|
7
|
-
"version": "1.1.
|
|
7
|
+
"version": "1.1.17",
|
|
8
8
|
"description": "",
|
|
9
9
|
"publishConfig": {
|
|
10
10
|
"access": "public"
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"author": "",
|
|
14
14
|
"license": "ISC",
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@dative-gpi/foundation-shared-domain": "1.1.
|
|
17
|
-
"@dative-gpi/foundation-shared-services": "1.1.
|
|
16
|
+
"@dative-gpi/foundation-shared-domain": "1.1.17",
|
|
17
|
+
"@dative-gpi/foundation-shared-services": "1.1.17"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"@dative-gpi/bones-ui": "^1.0.0",
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"sass": "1.71.1",
|
|
39
39
|
"sass-loader": "13.3.2"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "5486c2e9a50444f235f00c57fc4e32663cb15b25"
|
|
42
42
|
}
|