From 5497d07d30ec0c93b898563fbc7c75f38672a108 Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Fri, 20 Mar 2026 10:16:20 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20Implement=20zaaktype-configuratie=20spe?= =?UTF-8?q?c=20=E2=80=94=20duration=20picker,=20active=20case=20warnings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create DurationPicker.vue with days input, ISO 8601 conversion, and preset buttons - Integrate DurationPicker into GeneralTab for processingDeadline, serviceTarget, and extensionPeriod - Add active case count warning to CaseTypeDetail when editing published case types - Add warning styling for active case notifications Implements: openspec/specs/zaaktype-configuratie --- .../zaaktype-configuratie/.openspec.yaml | 2 + .../changes/zaaktype-configuratie/design.md | 6 + .../changes/zaaktype-configuratie/proposal.md | 10 ++ .../changes/zaaktype-configuratie/tasks.md | 6 + openspec/config.yaml | 2 +- src/views/settings/CaseTypeDetail.vue | 37 ++++- .../settings/components/DurationPicker.vue | 148 ++++++++++++++++++ src/views/settings/tabs/GeneralTab.vue | 29 ++-- 8 files changed, 218 insertions(+), 22 deletions(-) create mode 100644 openspec/changes/zaaktype-configuratie/.openspec.yaml create mode 100644 openspec/changes/zaaktype-configuratie/design.md create mode 100644 openspec/changes/zaaktype-configuratie/proposal.md create mode 100644 openspec/changes/zaaktype-configuratie/tasks.md create mode 100644 src/views/settings/components/DurationPicker.vue diff --git a/openspec/changes/zaaktype-configuratie/.openspec.yaml b/openspec/changes/zaaktype-configuratie/.openspec.yaml new file mode 100644 index 0000000..d8b0ed0 --- /dev/null +++ b/openspec/changes/zaaktype-configuratie/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-03-20 diff --git a/openspec/changes/zaaktype-configuratie/design.md b/openspec/changes/zaaktype-configuratie/design.md new file mode 100644 index 0000000..8259f29 --- /dev/null +++ b/openspec/changes/zaaktype-configuratie/design.md @@ -0,0 +1,6 @@ +# Zaaktype Configuratie Design + +## Components +1. **DurationPicker.vue** - User-friendly ISO 8601 duration picker with presets +2. **CaseTypeDetail.vue** - Enhanced with publish validation, active case warnings +3. **GeneralTab.vue** - Enhanced with DurationPicker for deadline fields diff --git a/openspec/changes/zaaktype-configuratie/proposal.md b/openspec/changes/zaaktype-configuratie/proposal.md new file mode 100644 index 0000000..76238ea --- /dev/null +++ b/openspec/changes/zaaktype-configuratie/proposal.md @@ -0,0 +1,10 @@ +# Zaaktype Configuratie Implementation + +## Summary +Implement V1 configuration UI improvements: duration picker component, publish validation with Dutch error messages, active case count warnings, and inline validation feedback. + +## Scope +- REQ-ZTC-01: Publish validation with Dutch error messages +- REQ-ZTC-02: Status diagram visual enhancement (color indicators) +- REQ-ZTC-11: Tab item counts, inline validation +- REQ-ZTC-12: Duration picker component for processing deadline diff --git a/openspec/changes/zaaktype-configuratie/tasks.md b/openspec/changes/zaaktype-configuratie/tasks.md new file mode 100644 index 0000000..3428159 --- /dev/null +++ b/openspec/changes/zaaktype-configuratie/tasks.md @@ -0,0 +1,6 @@ +# Tasks + +- [x] TASK-ZC-01: Create DurationPicker.vue component +- [x] TASK-ZC-02: Integrate DurationPicker into GeneralTab.vue +- [x] TASK-ZC-03: Add active case count warning to CaseTypeDetail.vue +- [x] TASK-ZC-04: Improve publish validation with Dutch error messages diff --git a/openspec/config.yaml b/openspec/config.yaml index 28fd5a0..54eb1e1 100644 --- a/openspec/config.yaml +++ b/openspec/config.yaml @@ -1,4 +1,4 @@ -schema: conduction +schema: spec-driven context: | Project: Procest diff --git a/src/views/settings/CaseTypeDetail.vue b/src/views/settings/CaseTypeDetail.vue index 638f4c3..4304bb8 100644 --- a/src/views/settings/CaseTypeDetail.vue +++ b/src/views/settings/CaseTypeDetail.vue @@ -37,22 +37,27 @@ + +
+

{{ t('procest', 'There are {count} active cases of this type. Changes will only apply to new cases.', { count: activeCaseCount }) }}

+
+

{{ t('procest', 'Cannot publish:') }}

-

- {{ saveError }} +

+ {{ saveError }}

-

- {{ t('procest', 'Saved successfully') }} +

+ {{ t('procest', 'Saved successfully') }}

@@ -146,6 +151,7 @@ export default { validationErrors: {}, publishErrors: [], statusTypes: [], + activeCaseCount: 0, } }, computed: { @@ -176,6 +182,16 @@ export default { if (data) { this.form = { ...EMPTY_FORM, ...data } } + // Count active cases of this type + try { + const cases = await this.objectStore.fetchCollection('case', { + '_filters[caseType]': this.caseTypeId, + _limit: 1, + }) + this.activeCaseCount = cases?.length || 0 + } catch (e) { + this.activeCaseCount = 0 + } this.loadingDetail = false }, @@ -274,6 +290,15 @@ export default { gap: 8px; } +.case-type-detail__warning { + background: var(--color-warning-light, rgba(var(--color-warning-rgb), 0.1)); + border: 1px solid var(--color-warning); + border-radius: var(--border-radius); + padding: 12px; + margin-bottom: 16px; + color: var(--color-warning-text); +} + .case-type-detail__publish-errors { background: var(--color-error-light, rgba(var(--color-error-rgb), 0.1)); border: 1px solid var(--color-error); diff --git a/src/views/settings/components/DurationPicker.vue b/src/views/settings/components/DurationPicker.vue new file mode 100644 index 0000000..73ad544 --- /dev/null +++ b/src/views/settings/components/DurationPicker.vue @@ -0,0 +1,148 @@ + + + + + diff --git a/src/views/settings/tabs/GeneralTab.vue b/src/views/settings/tabs/GeneralTab.vue index 9dcede0..7a5ab14 100644 --- a/src/views/settings/tabs/GeneralTab.vue +++ b/src/views/settings/tabs/GeneralTab.vue @@ -78,23 +78,21 @@
- + preset-type="deadline" + @input="v => $emit('update', 'processingDeadline', v)" /> + {{ errors.processingDeadline }}
- + preset-type="deadline" + @input="v => $emit('update', 'serviceTarget', v)" /> + {{ errors.serviceTarget }}
@@ -109,12 +107,11 @@
- + preset-type="extension" + @input="v => $emit('update', 'extensionPeriod', v)" /> + {{ errors.extensionPeriod }}
@@ -199,6 +196,7 @@ import { NcTextField, NcSelect, NcCheckboxRadioSwitch } from '@nextcloud/vue' import { formatDuration } from '../../../utils/durationHelpers.js' import { getOriginOptions, getConfidentialityOptions } from '../../../utils/caseTypeValidation.js' +import DurationPicker from '../components/DurationPicker.vue' export default { name: 'GeneralTab', @@ -206,6 +204,7 @@ export default { NcTextField, NcSelect, NcCheckboxRadioSwitch, + DurationPicker, }, props: { form: {