chore: add start and prestart scripts to package.json for improved application startup process

This commit is contained in:
Jennie Robinson Faber 2025-08-16 17:41:41 +01:00
parent fa48cd01b2
commit f935380781

View file

@ -5,15 +5,16 @@
<!-- Export Options - Top --> <!-- Export Options - Top -->
<div class="flex justify-center py-6"> <div class="flex justify-center py-6">
<ExportOptions <ExportOptions
:export-data="exportData" :export-data="exportData"
filename="conflict-resolution-framework" filename="conflict-resolution-framework"
title="Conflict Resolution Framework" title="Conflict Resolution Framework"
/> />
</div> </div>
<div <div
class="template-wrapper bg-white dark:bg-neutral-950 text-neutral-900 dark:text-neutral-100"> class="template-wrapper bg-white dark:bg-neutral-950 text-neutral-900 dark:text-neutral-100"
>
<!-- Document Container --> <!-- Document Container -->
<div class="document-page"> <div class="document-page">
<div class="template-content"> <div class="template-content">
@ -21,7 +22,8 @@
<div class="text-center mb-8"> <div class="text-center mb-8">
<h1 <h1
class="text-3xl md:text-5xl font-bold uppercase m-0 py-4 border-t-2 border-b-2 text-black dark:text-white border-black dark:border-white" class="text-3xl md:text-5xl font-bold uppercase m-0 py-4 border-t-2 border-b-2 text-black dark:text-white border-black dark:border-white"
:data-org-name="formData.orgName || 'Organization'"> :data-org-name="formData.orgName || 'Organization'"
>
CONFLICT RESOLUTION FRAMEWORK CONFLICT RESOLUTION FRAMEWORK
</h1> </h1>
</div> </div>
@ -38,7 +40,8 @@
size="xl" size="xl"
class="w-full" class="w-full"
:error="validationErrors.orgName" :error="validationErrors.orgName"
@input="debouncedAutoSave" /> @input="debouncedAutoSave"
/>
</UFormField> </UFormField>
<div class="flex flex-row gap-4 space-x-4"> <div class="flex flex-row gap-4 space-x-4">
<UFormField label="Organization Type" class="form-group-large"> <UFormField label="Organization Type" class="form-group-large">
@ -49,12 +52,11 @@
size="xl" size="xl"
class="w-full" class="w-full"
:error="validationErrors.orgType" :error="validationErrors.orgType"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<UFormField <UFormField label="Number of Members/Staff" class="form-group-large">
label="Number of Members/Staff"
class="form-group-large">
<UInput <UInput
v-model="formData.memberCount" v-model="formData.memberCount"
type="number" type="number"
@ -62,7 +64,8 @@
placeholder="e.g., 5" placeholder="e.g., 5"
size="xl" size="xl"
:error="validationErrors.memberCount" :error="validationErrors.memberCount"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
</div> </div>
</div> </div>
@ -79,38 +82,44 @@
label="Include this section" label="Include this section"
:ui="{ :ui="{
label: 'text-xs text-neutral-700 dark:text-neutral-300', label: 'text-xs text-neutral-700 dark:text-neutral-300',
}" /> }"
/>
</div> </div>
</div> </div>
<div class="space-y-6" v-show="sectionsEnabled.values"> <div class="space-y-6" v-show="sectionsEnabled.values">
<UFormField <UFormField
label="Select Core Values (check all that apply)" label="Select Core Values (check all that apply)"
class="form-group-large"> class="form-group-large"
>
<div class="values-grid"> <div class="values-grid">
<div <div
v-for="(value, index) in coreValues" v-for="(value, index) in coreValues"
:key="index" :key="index"
class="checkbox-item"> class="checkbox-item"
>
<UCheckbox <UCheckbox
v-model="value.checked" v-model="value.checked"
:id="`core-value-${index}`" :id="`core-value-${index}`"
:label="value.label" :label="value.label"
@change="autoSave" /> @change="autoSave"
/>
</div> </div>
</div> </div>
</UFormField> </UFormField>
<UFormField <UFormField
label="Additional Values or Principles" label="Additional Values or Principles"
class="form-group-large"> class="form-group-large"
>
<UTextarea <UTextarea
v-model="formData.customValues" v-model="formData.customValues"
:rows="3" :rows="3"
placeholder="Add any additional values specific to your organization..." placeholder="Add any additional values specific to your organization..."
size="xl" size="xl"
class="w-full" class="w-full"
@input="debouncedAutoSave" /> @input="debouncedAutoSave"
/>
</UFormField> </UFormField>
</div> </div>
</div> </div>
@ -126,12 +135,14 @@
<div <div
v-for="(conflict, index) in conflictTypes" v-for="(conflict, index) in conflictTypes"
:key="index" :key="index"
class="checkbox-item"> class="checkbox-item"
>
<UCheckbox <UCheckbox
v-model="conflict.checked" v-model="conflict.checked"
:id="`conflict-type-${index}`" :id="`conflict-type-${index}`"
:label="conflict.label" :label="conflict.label"
@change="autoSave" /> @change="autoSave"
/>
</div> </div>
</div> </div>
<div v-if="validationErrors.conflictTypes" class="validation-error"> <div v-if="validationErrors.conflictTypes" class="validation-error">
@ -144,14 +155,14 @@
<h2 class="section-title">4. Primary Resolution Approach</h2> <h2 class="section-title">4. Primary Resolution Approach</h2>
<div class="space-y-6"> <div class="space-y-6">
<UFormField <UFormField label="Choose your primary conflict resolution philosophy:">
label="Choose your primary conflict resolution philosophy:">
<URadioGroup <URadioGroup
v-model="formData.approach" v-model="formData.approach"
:items="approachOptions" :items="approachOptions"
variant="card" variant="card"
size="lg" size="lg"
class="mt-2" /> class="mt-2"
/>
<div v-if="validationErrors.approach" class="validation-error"> <div v-if="validationErrors.approach" class="validation-error">
{{ validationErrors.approach }} {{ validationErrors.approach }}
</div> </div>
@ -163,7 +174,8 @@
id="anonymous-reporting" id="anonymous-reporting"
label="Allow anonymous reporting" label="Allow anonymous reporting"
help="Members can report issues without revealing their identity" help="Members can report issues without revealing their identity"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
</div> </div>
</div> </div>
@ -175,36 +187,36 @@
<div class="space-y-6"> <div class="space-y-6">
<UFormField <UFormField
label="Who can receive initial conflict reports? (check all that apply)" label="Who can receive initial conflict reports? (check all that apply)"
class="form-group-large"> class="form-group-large"
>
<div class="checkbox-group space-y-2 mt-4"> <div class="checkbox-group space-y-2 mt-4">
<div <div
v-for="(receiver, index) in reportReceivers" v-for="(receiver, index) in reportReceivers"
:key="index" :key="index"
class="checkbox-item"> class="checkbox-item"
>
<UCheckbox <UCheckbox
v-model="receiver.checked" v-model="receiver.checked"
:id="`report-receiver-${index}`" :id="`report-receiver-${index}`"
:label="receiver.label" :label="receiver.label"
@change="autoSave" /> @change="autoSave"
/>
</div> </div>
</div> </div>
<div <div v-if="validationErrors.reportReceivers" class="validation-error">
v-if="validationErrors.reportReceivers"
class="validation-error">
{{ validationErrors.reportReceivers }} {{ validationErrors.reportReceivers }}
</div> </div>
</UFormField> </UFormField>
<UFormField <UFormField label="Mediator/Facilitator Structure" class="form-group-large">
label="Mediator/Facilitator Structure"
class="form-group-large">
<USelect <USelect
v-model="formData.mediatorType" v-model="formData.mediatorType"
:items="mediatorTypeOptions" :items="mediatorTypeOptions"
placeholder="Select mediator structure..." placeholder="Select mediator structure..."
size="xl" size="xl"
:error="validationErrors.mediatorType" :error="validationErrors.mediatorType"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<UFormField class="form-group-large"> <UFormField class="form-group-large">
@ -213,7 +225,8 @@
id="support-people" id="support-people"
label="Allow support people in mediation sessions" label="Allow support people in mediation sessions"
help="Parties can bring a trusted person for emotional support" help="Parties can bring a trusted person for emotional support"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
</div> </div>
</div> </div>
@ -224,9 +237,7 @@
<div class="space-y-6"> <div class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<UFormField <UFormField label="Initial Response Time" class="form-group-large">
label="Initial Response Time"
class="form-group-large">
<USelect <USelect
v-model="formData.initialResponse" v-model="formData.initialResponse"
:items="responseTimeOptions" :items="responseTimeOptions"
@ -234,12 +245,11 @@
size="xl" size="xl"
class="w-full" class="w-full"
:error="validationErrors.initialResponse" :error="validationErrors.initialResponse"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<UFormField <UFormField label="Target Resolution Time" class="form-group-large">
label="Target Resolution Time"
class="form-group-large">
<USelect <USelect
v-model="formData.resolutionTarget" v-model="formData.resolutionTarget"
:items="resolutionTimeOptions" :items="resolutionTimeOptions"
@ -247,28 +257,30 @@
size="xl" size="xl"
class="w-full" class="w-full"
:error="validationErrors.resolutionTarget" :error="validationErrors.resolutionTarget"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
</div> </div>
<UFormField <UFormField
label="Process Steps (select applicable steps)" label="Process Steps (select applicable steps)"
class="form-group-large"> class="form-group-large"
>
<div class="checkbox-group mt-4 space-y-3"> <div class="checkbox-group mt-4 space-y-3">
<div <div
v-for="(step, index) in processSteps" v-for="(step, index) in processSteps"
:key="index" :key="index"
class="checkbox-item"> class="checkbox-item"
>
<UCheckbox <UCheckbox
v-model="step.checked" v-model="step.checked"
:id="`process-step-${index}`" :id="`process-step-${index}`"
:label="`${index + 1}. ${step.label}`" :label="`${index + 1}. ${step.label}`"
@change="autoSave" /> @change="autoSave"
/>
</div> </div>
</div> </div>
<div <div v-if="validationErrors.processSteps" class="validation-error">
v-if="validationErrors.processSteps"
class="validation-error">
{{ validationErrors.processSteps }} {{ validationErrors.processSteps }}
</div> </div>
</UFormField> </UFormField>
@ -277,8 +289,7 @@
<!-- Section 7: Documentation & Privacy --> <!-- Section 7: Documentation & Privacy -->
<div class="section-card"> <div class="section-card">
<div <div class="section-header flex flex-row justify-between items-center">
class="section-header flex flex-row justify-between items-center">
<h2 class="section-title">7. Documentation & Privacy</h2> <h2 class="section-title">7. Documentation & Privacy</h2>
<div class="flex flex-row gap-2 items-center no-print no-pdf"> <div class="flex flex-row gap-2 items-center no-print no-pdf">
<USwitch <USwitch
@ -287,7 +298,8 @@
label="Include this section" label="Include this section"
:ui="{ :ui="{
label: 'text-xs text-neutral-700 dark:text-neutral-300', label: 'text-xs text-neutral-700 dark:text-neutral-300',
}" /> }"
/>
</div> </div>
</div> </div>
@ -299,31 +311,30 @@
placeholder="Select documentation level..." placeholder="Select documentation level..."
size="xl" size="xl"
class="w-full" class="w-full"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<UFormField <UFormField label="Confidentiality Level" class="form-group-large">
label="Confidentiality Level"
class="form-group-large">
<USelect <USelect
v-model="formData.confidentiality" v-model="formData.confidentiality"
:items="confidentialityOptions" :items="confidentialityOptions"
placeholder="Select confidentiality level..." placeholder="Select confidentiality level..."
size="xl" size="xl"
class="w-full" class="w-full"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<UFormField <UFormField label="Record Retention Period" class="form-group-large">
label="Record Retention Period"
class="form-group-large">
<USelect <USelect
v-model="formData.retention" v-model="formData.retention"
:items="retentionOptions" :items="retentionOptions"
placeholder="Select retention period..." placeholder="Select retention period..."
size="xl" size="xl"
class="w-full" class="w-full"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
</div> </div>
</div> </div>
@ -335,42 +346,44 @@
<div class="space-y-6"> <div class="space-y-6">
<UFormField <UFormField
label="Available Actions (check all that apply)" label="Available Actions (check all that apply)"
class="form-group-large"> class="form-group-large"
>
<div class="checkbox-group mt-4 space-y-3"> <div class="checkbox-group mt-4 space-y-3">
<div <div
v-for="(action, index) in availableActions" v-for="(action, index) in availableActions"
:key="index" :key="index"
class="checkbox-item"> class="checkbox-item"
>
<UCheckbox <UCheckbox
v-model="action.checked" v-model="action.checked"
:id="`available-action-${index}`" :id="`available-action-${index}`"
:label="action.label" :label="action.label"
@change="autoSave" /> @change="autoSave"
/>
</div> </div>
</div> </div>
<div <div v-if="validationErrors.availableActions" class="validation-error">
v-if="validationErrors.availableActions"
class="validation-error">
{{ validationErrors.availableActions }} {{ validationErrors.availableActions }}
</div> </div>
</UFormField> </UFormField>
<UFormField <UFormField
class="form-group-large border-t border-neutral-200 dark:border-neutral-800 pt-4"> class="form-group-large border-t border-neutral-200 dark:border-neutral-800 pt-4"
>
<UCheckbox <UCheckbox
v-model="formData.appealProcess" v-model="formData.appealProcess"
id="appeal-process" id="appeal-process"
label="Include appeals process" label="Include appeals process"
help="Parties can request review of decisions" help="Parties can request review of decisions"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
</div> </div>
</div> </div>
<!-- Section 9: Special Circumstances --> <!-- Section 9: Special Circumstances -->
<div class="section-card"> <div class="section-card">
<div <div class="section-header flex flex-row justify-between items-center">
class="section-header flex flex-row justify-between items-center">
<h2 class="section-title">9. Special Circumstances</h2> <h2 class="section-title">9. Special Circumstances</h2>
<div class="flex flex-row gap-2 items-center no-print no-pdf"> <div class="flex flex-row gap-2 items-center no-print no-pdf">
<USwitch <USwitch
@ -379,7 +392,8 @@
label="Include this section" label="Include this section"
:ui="{ :ui="{
label: 'text-xs text-neutral-700 dark:text-neutral-300', label: 'text-xs text-neutral-700 dark:text-neutral-300',
}" /> }"
/>
</div> </div>
</div> </div>
@ -388,12 +402,14 @@
<div <div
v-for="(circumstance, index) in specialCircumstances" v-for="(circumstance, index) in specialCircumstances"
:key="index" :key="index"
class="checkbox-item"> class="checkbox-item"
>
<UCheckbox <UCheckbox
v-model="circumstance.checked" v-model="circumstance.checked"
:id="`special-circumstance-${index}`" :id="`special-circumstance-${index}`"
:label="circumstance.label" :label="circumstance.label"
@change="autoSave" /> @change="autoSave"
/>
</div> </div>
</div> </div>
</div> </div>
@ -404,22 +420,19 @@
<h2 class="section-title">10. Implementation Details</h2> <h2 class="section-title">10. Implementation Details</h2>
<div class="space-y-6"> <div class="space-y-6">
<UFormField <UFormField label="Training Requirements" class="form-group-large">
label="Training Requirements"
class="form-group-large">
<UTextarea <UTextarea
v-model="formData.training" v-model="formData.training"
:rows="3" :rows="3"
class="w-full" class="w-full"
placeholder="Describe any training needed for members, facilitators, or committee members..." placeholder="Describe any training needed for members, facilitators, or committee members..."
size="xl" size="xl"
@input="debouncedAutoSave" /> @input="debouncedAutoSave"
/>
</UFormField> </UFormField>
<div class="flex flex-row space-x-4"> <div class="flex flex-row space-x-4">
<UFormField <UFormField label="Policy Review Schedule" class="form-group-large">
label="Policy Review Schedule"
class="form-group-large">
<USelect <USelect
v-model="formData.reviewSchedule" v-model="formData.reviewSchedule"
:items="reviewScheduleOptions" :items="reviewScheduleOptions"
@ -427,11 +440,13 @@
size="xl" size="xl"
class="w-full" class="w-full"
:error="validationErrors.reviewSchedule" :error="validationErrors.reviewSchedule"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<UFormField <UFormField
label="How can this policy be amended?" label="How can this policy be amended?"
class="form-group-large"> class="form-group-large"
>
<USelect <USelect
v-model="formData.amendments" v-model="formData.amendments"
:items="amendmentOptions" :items="amendmentOptions"
@ -439,7 +454,8 @@
size="xl" size="xl"
class="w-full" class="w-full"
:error="validationErrors.amendments" :error="validationErrors.amendments"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
</div> </div>
@ -451,7 +467,8 @@
type="date" type="date"
size="xl" size="xl"
class="w-full mb-0" class="w-full mb-0"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<UFormField label="Next Review Date"> <UFormField label="Next Review Date">
@ -460,7 +477,8 @@
type="date" type="date"
size="xl" size="xl"
class="w-full mb-0" class="w-full mb-0"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
</div> </div>
</div> </div>
@ -469,8 +487,7 @@
<!-- Section 11: Reflection Process --> <!-- Section 11: Reflection Process -->
<div class="section-card"> <div class="section-card">
<div <div class="section-header flex flex-row justify-between items-center">
class="section-header flex flex-row justify-between items-center">
<h2 class="section-title">11. Reflection Process</h2> <h2 class="section-title">11. Reflection Process</h2>
<div class="flex flex-row gap-2 items-center no-print no-pdf"> <div class="flex flex-row gap-2 items-center no-print no-pdf">
<USwitch <USwitch
@ -479,41 +496,39 @@
label="Include detailed reflection guidance" label="Include detailed reflection guidance"
:ui="{ :ui="{
label: 'text-xs text-neutral-700 dark:text-neutral-300', label: 'text-xs text-neutral-700 dark:text-neutral-300',
}" /> }"
/>
</div> </div>
</div> </div>
<div class="space-y-6" v-show="sectionsEnabled.reflection"> <div class="space-y-6" v-show="sectionsEnabled.reflection">
<UFormField <UFormField label="Reflection Period Timeframe" class="form-group-large">
label="Reflection Period Timeframe"
class="form-group-large">
<USelect <USelect
v-model="formData.reflectionPeriod" v-model="formData.reflectionPeriod"
:items="reflectionPeriodOptions" :items="reflectionPeriodOptions"
placeholder="Select reflection timeframe..." placeholder="Select reflection timeframe..."
size="xl" size="xl"
class="w-full md:w-1/2 mt-2" class="w-full md:w-1/2 mt-2"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<UFormField <UFormField label="Additional Reflection Prompts" class="form-group-large">
label="Additional Reflection Prompts"
class="form-group-large">
<UTextarea <UTextarea
v-model="formData.customReflectionPrompts" v-model="formData.customReflectionPrompts"
:rows="4" :rows="4"
placeholder="Add any organization-specific reflection questions or prompts..." placeholder="Add any organization-specific reflection questions or prompts..."
size="xl" size="xl"
class="w-full mt-2" class="w-full mt-2"
@input="debouncedAutoSave" /> @input="debouncedAutoSave"
/>
</UFormField> </UFormField>
</div> </div>
</div> </div>
<!-- Section 12: Direct Resolution Guidelines --> <!-- Section 12: Direct Resolution Guidelines -->
<div class="section-card"> <div class="section-card">
<div <div class="section-header flex flex-row justify-between items-center">
class="section-header flex flex-row justify-between items-center">
<h2 class="section-title">12. Direct Resolution Guidelines</h2> <h2 class="section-title">12. Direct Resolution Guidelines</h2>
<div class="flex flex-row gap-2 items-center no-print no-pdf"> <div class="flex flex-row gap-2 items-center no-print no-pdf">
<USwitch <USwitch
@ -522,90 +537,99 @@
label="Include detailed conversation guidance" label="Include detailed conversation guidance"
:ui="{ :ui="{
label: 'text-xs text-neutral-700 dark:text-neutral-300', label: 'text-xs text-neutral-700 dark:text-neutral-300',
}" /> }"
/>
</div> </div>
</div> </div>
<div class="space-y-6" v-show="sectionsEnabled.directResolution"> <div class="space-y-6" v-show="sectionsEnabled.directResolution">
<UFormField <UFormField
label="Communication Channels (select preferred escalation order)" label="Communication Channels (select preferred escalation order)"
class="form-group-large"> class="form-group-large"
>
<div class="checkbox-group space-y-3 mt-4"> <div class="checkbox-group space-y-3 mt-4">
<div <div
v-for="(channel, index) in communicationChannels" v-for="(channel, index) in communicationChannels"
:key="index" :key="index"
class="checkbox-item"> class="checkbox-item"
>
<UCheckbox <UCheckbox
v-model="channel.checked" v-model="channel.checked"
:id="`comm-channel-${index}`" :id="`comm-channel-${index}`"
:label="channel.label" :label="channel.label"
@change="autoSave" /> @change="autoSave"
/>
</div> </div>
</div> </div>
</UFormField> </UFormField>
<UFormField <UFormField
class="form-group-large border-t border-neutral-200 dark:border-neutral-800 pt-4"> class="form-group-large border-t border-neutral-200 dark:border-neutral-800 pt-4"
>
<UCheckbox <UCheckbox
v-model="formData.requireDirectAttempt" v-model="formData.requireDirectAttempt"
id="require-direct-attempt" id="require-direct-attempt"
label="Require direct resolution attempt before escalation" label="Require direct resolution attempt before escalation"
help="Parties must try to resolve directly before filing complaints" help="Parties must try to resolve directly before filing complaints"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<UFormField <UFormField
class="form-group-large border-t border-neutral-200 dark:border-neutral-800 pt-4"> class="form-group-large border-t border-neutral-200 dark:border-neutral-800 pt-4"
>
<UCheckbox <UCheckbox
v-model="formData.documentDirectResolution" v-model="formData.documentDirectResolution"
id="document-direct-resolution" id="document-direct-resolution"
label="Require written record of direct resolution attempts" label="Require written record of direct resolution attempts"
help="Parties should document outcomes of direct conversations" help="Parties should document outcomes of direct conversations"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
</div> </div>
</div> </div>
<!-- Section 13: Responsible Contact People --> <!-- Section 13: Responsible Contact People -->
<div class="section-card"> <div class="section-card">
<h2 class="section-title"> <h2 class="section-title">13. Responsible Contact People Structure</h2>
13. Responsible Contact People Structure
</h2>
<div class="space-y-6"> <div class="space-y-6">
<UFormField <UFormField label="Internal Advisor Designation" class="form-group-large">
label="Internal Advisor Designation"
class="form-group-large">
<USelect <USelect
v-model="formData.internalAdvisorType" v-model="formData.internalAdvisorType"
:items="internalAdvisorOptions" :items="internalAdvisorOptions"
placeholder="Select internal advisor structure..." placeholder="Select internal advisor structure..."
class="w-full md:w-1/2" class="w-full md:w-1/2"
size="xl" size="xl"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<UFormField <UFormField
label="Staff Liaison for Conflict Resolution Committee" label="Staff Liaison for Conflict Resolution Committee"
class="form-group-large"> class="form-group-large"
>
<UInput <UInput
v-model="formData.staffLiaison" v-model="formData.staffLiaison"
placeholder="Title/role of designated staff liaison" placeholder="Title/role of designated staff liaison"
size="xl" size="xl"
class="w-full md:w-1/2" class="w-full md:w-1/2"
@input="debouncedAutoSave" /> @input="debouncedAutoSave"
/>
</UFormField> </UFormField>
<UFormField <UFormField
label="Board Chair Role in Conflict Resolution" label="Board Chair Role in Conflict Resolution"
class="form-group-large"> class="form-group-large"
>
<USelect <USelect
v-model="formData.boardChairRole" v-model="formData.boardChairRole"
:items="boardChairRoleOptions" :items="boardChairRoleOptions"
placeholder="Select board chair involvement..." placeholder="Select board chair involvement..."
size="xl" size="xl"
class="w-full md:w-1/2" class="w-full md:w-1/2"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
</div> </div>
</div> </div>
@ -615,19 +639,19 @@
<h2 class="section-title">14. Formal Complaint Requirements</h2> <h2 class="section-title">14. Formal Complaint Requirements</h2>
<div class="space-y-6"> <div class="space-y-6">
<UFormField <UFormField label="Required Complaint Elements" class="form-group-large">
label="Required Complaint Elements"
class="form-group-large">
<div class="checkbox-group space-y-3 mt-4"> <div class="checkbox-group space-y-3 mt-4">
<div <div
v-for="(element, index) in formalComplaintElements" v-for="(element, index) in formalComplaintElements"
:key="index" :key="index"
class="checkbox-item"> class="checkbox-item"
>
<UCheckbox <UCheckbox
v-model="element.checked" v-model="element.checked"
:id="`complaint-element-${index}`" :id="`complaint-element-${index}`"
:label="element.label" :label="element.label"
@change="autoSave" /> @change="autoSave"
/>
</div> </div>
</div> </div>
</UFormField> </UFormField>
@ -635,26 +659,30 @@
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<UFormField <UFormField
label="Formal Complaint Acknowledgment Time" label="Formal Complaint Acknowledgment Time"
class="form-group-large"> class="form-group-large"
>
<USelect <USelect
v-model="formData.formalAcknowledgmentTime" v-model="formData.formalAcknowledgmentTime"
:items="acknowledgmentTimeOptions" :items="acknowledgmentTimeOptions"
placeholder="Select acknowledgment timeframe..." placeholder="Select acknowledgment timeframe..."
class="w-full" class="w-full"
size="xl" size="xl"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<UFormField <UFormField
label="Formal Review Completion Time" label="Formal Review Completion Time"
class="form-group-large"> class="form-group-large"
>
<USelect <USelect
v-model="formData.formalReviewTime" v-model="formData.formalReviewTime"
:items="reviewTimeOptions" :items="reviewTimeOptions"
placeholder="Select review timeframe..." placeholder="Select review timeframe..."
size="xl" size="xl"
class="w-full" class="w-full"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
</div> </div>
@ -664,7 +692,8 @@
id="require-external-advice" id="require-external-advice"
label="Require external legal advice for complex complaints" label="Require external legal advice for complex complaints"
help="Seek external expertise for multi-party or staff/director complaints" help="Seek external expertise for multi-party or staff/director complaints"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
</div> </div>
</div> </div>
@ -680,31 +709,36 @@
id="minutes-of-settlement" id="minutes-of-settlement"
label="Require 'Minutes of Settlement' for resolved complaints" label="Require 'Minutes of Settlement' for resolved complaints"
help="Agreements must be documented in writing and signed by both parties" help="Agreements must be documented in writing and signed by both parties"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<div class="flex flex-row space-x-4"> <div class="flex flex-row space-x-4">
<UFormField <UFormField
label="Settlement Confidentiality Level" label="Settlement Confidentiality Level"
class="form-group-large"> class="form-group-large"
>
<USelect <USelect
v-model="formData.settlementConfidentiality" v-model="formData.settlementConfidentiality"
:items="confidentialityOptions" :items="confidentialityOptions"
placeholder="Select confidentiality level..." placeholder="Select confidentiality level..."
size="xl" size="xl"
class="w-full" class="w-full"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<UFormField <UFormField
label="Conflict Resolution File Retention" label="Conflict Resolution File Retention"
class="form-group-large"> class="form-group-large"
>
<USelect <USelect
v-model="formData.conflictFileRetention" v-model="formData.conflictFileRetention"
:items="retentionOptions" :items="retentionOptions"
placeholder="Select retention period..." placeholder="Select retention period..."
size="xl" size="xl"
class="w-full" class="w-full"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
</div> </div>
</div> </div>
@ -712,8 +746,7 @@
<!-- Section 16: External Resources --> <!-- Section 16: External Resources -->
<div class="section-card"> <div class="section-card">
<div <div class="section-header flex flex-row justify-between items-center">
class="section-header flex flex-row justify-between items-center">
<h2 class="section-title">16. External Resources & Redress</h2> <h2 class="section-title">16. External Resources & Redress</h2>
<div class="flex flex-row gap-2 items-center no-print no-pdf"> <div class="flex flex-row gap-2 items-center no-print no-pdf">
<USwitch <USwitch
@ -722,7 +755,8 @@
label="Include external resource information" label="Include external resource information"
:ui="{ :ui="{
label: 'text-xs text-neutral-700 dark:text-neutral-300', label: 'text-xs text-neutral-700 dark:text-neutral-300',
}" /> }"
/>
</div> </div>
</div> </div>
@ -733,31 +767,30 @@
id="include-human-rights" id="include-human-rights"
label="Include Human Rights Commission information" label="Include Human Rights Commission information"
help="Reference external discrimination complaint options" help="Reference external discrimination complaint options"
@change="autoSave" /> @change="autoSave"
/>
</UFormField> </UFormField>
<UFormField <UFormField label="Additional External Resources" class="form-group-large">
label="Additional External Resources"
class="form-group-large">
<UTextarea <UTextarea
v-model="formData.additionalResources" v-model="formData.additionalResources"
:rows="3" :rows="3"
class="w-full" class="w-full"
placeholder="List any other external resources, legal aid contacts, or specialized support services..." placeholder="List any other external resources, legal aid contacts, or specialized support services..."
size="xl" size="xl"
@input="debouncedAutoSave" /> @input="debouncedAutoSave"
/>
</UFormField> </UFormField>
<UFormField <UFormField label="Acknowledgment/Attribution" class="form-group-large">
label="Acknowledgment/Attribution"
class="form-group-large">
<UTextarea <UTextarea
v-model="formData.acknowledgments" v-model="formData.acknowledgments"
:rows="2" :rows="2"
placeholder="Credit any sources used in developing this policy..." placeholder="Credit any sources used in developing this policy..."
class="w-full" class="w-full"
size="xl" size="xl"
@input="debouncedAutoSave" /> @input="debouncedAutoSave"
/>
</UFormField> </UFormField>
</div> </div>
</div> </div>
@ -765,20 +798,23 @@
<!-- Document Preview Section --> <!-- Document Preview Section -->
<div class="no-print" v-if="showPreview"> <div class="no-print" v-if="showPreview">
<div <div
class="border border-neutral-200 dark:border-neutral-800 bg-white dark:bg-neutral-950 p-5 rounded-lg shadow-sm"> class="border border-neutral-200 dark:border-neutral-800 bg-white dark:bg-neutral-950 p-5 rounded-lg shadow-sm"
>
<div class="flex flex-row justify-between items-center mb-4"> <div class="flex flex-row justify-between items-center mb-4">
<h2 class="section-title m-0">📄 Policy Document Preview</h2> <h2 class="section-title m-0">📄 Policy Document Preview</h2>
<UButton <UButton
size="sm" size="sm"
variant="ghost" variant="ghost"
@click="showPreview = false" @click="showPreview = false"
title="Hide preview"> title="Hide preview"
>
</UButton> </UButton>
</div> </div>
<div <div
class="policy-preview prose prose-neutral dark:prose-invert max-w-none px-6 py-5 bg-neutral-50 dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-800 rounded-md max-h-[600px] overflow-y-auto text-left" class="policy-preview prose prose-neutral dark:prose-invert max-w-none px-6 py-5 bg-neutral-50 dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-900 rounded-md max-h-[600px] overflow-y-auto text-left"
v-html="markdownToHtml(generatePolicyDocument())"></div> v-html="markdownToHtml(generatePolicyDocument())"
></div>
</div> </div>
</div> </div>
</div> </div>
@ -787,10 +823,10 @@
<!-- Export Options - Bottom --> <!-- Export Options - Bottom -->
<div class="flex justify-center py-6"> <div class="flex justify-center py-6">
<ExportOptions <ExportOptions
:export-data="exportData" :export-data="exportData"
filename="conflict-resolution-framework" filename="conflict-resolution-framework"
title="Conflict Resolution Framework" title="Conflict Resolution Framework"
/> />
</div> </div>
</div> </div>
@ -870,13 +906,7 @@ const responseTimeOptions = [
"Within 2 weeks", "Within 2 weeks",
]; ];
const resolutionTimeOptions = [ const resolutionTimeOptions = ["1 week", "2 weeks", "30 days", "60 days", "90 days"];
"1 week",
"2 weeks",
"30 days",
"60 days",
"90 days",
];
const docLevelOptions = [ const docLevelOptions = [
"Minimal - outcomes only", "Minimal - outcomes only",
@ -937,13 +967,7 @@ const acknowledgmentTimeOptions = [
"Within 2 weeks", "Within 2 weeks",
]; ];
const reviewTimeOptions = [ const reviewTimeOptions = ["2 weeks", "1 month", "6 weeks", "2 months", "3 months"];
"2 weeks",
"1 month",
"6 weeks",
"2 months",
"3 months",
];
const sectionsEnabled = ref({ const sectionsEnabled = ref({
values: true, values: true,
@ -1117,18 +1141,14 @@ const validateForm = () => {
} }
// Required checkbox groups (must have at least one checked) // Required checkbox groups (must have at least one checked)
const checkedConflictTypes = conflictTypes.value.filter( const checkedConflictTypes = conflictTypes.value.filter((item) => item.checked);
(item) => item.checked
);
if (checkedConflictTypes.length === 0) { if (checkedConflictTypes.length === 0) {
errors.conflictTypes = "Please select at least one type of conflict"; errors.conflictTypes = "Please select at least one type of conflict";
} }
// Note: Guiding Principles & Values section is optional - no validation needed // Note: Guiding Principles & Values section is optional - no validation needed
const checkedReportReceivers = reportReceivers.value.filter( const checkedReportReceivers = reportReceivers.value.filter((item) => item.checked);
(item) => item.checked
);
if (checkedReportReceivers.length === 0) { if (checkedReportReceivers.length === 0) {
errors.reportReceivers = "Please select at least one report receiver"; errors.reportReceivers = "Please select at least one report receiver";
} }
@ -1138,9 +1158,7 @@ const validateForm = () => {
errors.processSteps = "Please select at least one process step"; errors.processSteps = "Please select at least one process step";
} }
const checkedAvailableActions = availableActions.value.filter( const checkedAvailableActions = availableActions.value.filter((item) => item.checked);
(item) => item.checked
);
if (checkedAvailableActions.length === 0) { if (checkedAvailableActions.length === 0) {
errors.availableActions = "Please select at least one available action"; errors.availableActions = "Please select at least one available action";
} }
@ -1188,9 +1206,8 @@ const completionPercentage = computed(() => {
...specialCircumstances.value, ...specialCircumstances.value,
]; ];
const filledInputs = allInputs.filter( const filledInputs = allInputs.filter((val) => val && val.toString().trim() !== "")
(val) => val && val.toString().trim() !== "" .length;
).length;
const checkedBoxes = checkboxInputs.filter((item) => item.checked).length; const checkedBoxes = checkboxInputs.filter((item) => item.checked).length;
const totalFields = allInputs.length + checkboxInputs.length; const totalFields = allInputs.length + checkboxInputs.length;
@ -1214,12 +1231,10 @@ const loadSavedData = () => {
// Load checkbox arrays // Load checkbox arrays
if (parsedData.coreValues) coreValues.value = parsedData.coreValues; if (parsedData.coreValues) coreValues.value = parsedData.coreValues;
if (parsedData.conflictTypes) if (parsedData.conflictTypes) conflictTypes.value = parsedData.conflictTypes;
conflictTypes.value = parsedData.conflictTypes;
if (parsedData.reportReceivers) if (parsedData.reportReceivers)
reportReceivers.value = parsedData.reportReceivers; reportReceivers.value = parsedData.reportReceivers;
if (parsedData.processSteps) if (parsedData.processSteps) processSteps.value = parsedData.processSteps;
processSteps.value = parsedData.processSteps;
if (parsedData.availableActions) if (parsedData.availableActions)
availableActions.value = parsedData.availableActions; availableActions.value = parsedData.availableActions;
if (parsedData.specialCircumstances) if (parsedData.specialCircumstances)
@ -1369,12 +1384,11 @@ const exportData = computed(() => ({
finalDecision: formData.value.finalDecision, finalDecision: formData.value.finalDecision,
learning: formData.value.learning, learning: formData.value.learning,
emergencyProcedures: formData.value.emergencyProcedures, emergencyProcedures: formData.value.emergencyProcedures,
annualReview: formData.value.annualReview annualReview: formData.value.annualReview,
}, },
exportedAt: new Date().toISOString(), exportedAt: new Date().toISOString(),
section: "conflict-resolution-framework" section: "conflict-resolution-framework",
})); }));
</script> </script>
<style scoped> <style scoped>
@ -1397,11 +1411,7 @@ const exportData = computed(() => ({
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
background-image: radial-gradient( background-image: radial-gradient(circle at 25% 25%, black 1px, transparent 1px),
circle at 25% 25%,
black 1px,
transparent 1px
),
radial-gradient(circle at 75% 75%, black 1px, transparent 1px); radial-gradient(circle at 75% 75%, black 1px, transparent 1px);
background-size: 8px 8px, 8px 8px; background-size: 8px 8px, 8px 8px;
background-position: 0 0, 4px 4px; background-position: 0 0, 4px 4px;
@ -1793,8 +1803,8 @@ html.dark .policy-preview blockquote {
} }
.policy-preview code { .policy-preview code {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
"Liberation Mono", "Courier New", monospace !important; "Courier New", monospace !important;
background: #f3f4f6; background: #f3f4f6;
padding: 0.1rem 0.35rem; padding: 0.1rem 0.35rem;
} }