diff --git a/atst/forms/task_order.py b/atst/forms/task_order.py index 99c1e35d..fca7bcfd 100644 --- a/atst/forms/task_order.py +++ b/atst/forms/task_order.py @@ -51,6 +51,16 @@ class CLINForm(FlaskForm): ) loas = FieldList(StringField()) + def validate(self, *args, **kwargs): + valid = super().validate(*args, **kwargs) + if self.start_date.data > self.end_date.data: + self.start_date.errors.append( + translate("forms.task_order.start_date_error") + ) + return False + else: + return valid + class TaskOrderForm(BaseForm): number = StringField(label=translate("forms.task_order.number_description")) diff --git a/js/components/clin_fields.js b/js/components/clin_fields.js index b0805229..b00666fa 100644 --- a/js/components/clin_fields.js +++ b/js/components/clin_fields.js @@ -5,6 +5,9 @@ import textinput from './text_input' const JEDI_CLIN_TYPE = 'jedi_clin_type' const OBLIGATED_AMOUNT = 'obligated_amount' +const START_DATE = 'start_date' +const END_DATE = 'end_date' +const POP = 'period_of_performance' export default { name: 'clin-fields', @@ -26,11 +29,27 @@ export default { type: Number, default: 0, }, + initialStartDate: { + type: String, + default: null, + }, + initialEndDate: { + type: String, + default: null, + }, }, data: function() { const loas = this.initialLoaCount == 0 ? 1 : 0 const indexOffset = this.initialLoaCount + const start = !!this.initialStartDate + ? new Date(this.initialStartDate) + : undefined + const end = !!this.initialEndDate + ? new Date(this.initialEndDate) + : undefined + const popValidation = !this.initialStartDate ? false : start < end + const showPopValidation = !this.initialStartDate ? false : !popValidation return { clinIndex: this.initialClinIndex, @@ -38,6 +57,10 @@ export default { loas: loas, clinType: this.initialClinType, amount: this.initialAmount || 0, + startDate: start, + endDate: end, + popValid: popValidation, + showPopError: showPopValidation, } }, @@ -51,6 +74,11 @@ export default { clinType: this.clinType, amount: this.initialAmount, }) + emitEvent('field-mount', this, { + optional: false, + name: POP, + valid: this.checkPopValid(), + }) }, methods: { @@ -70,6 +98,23 @@ export default { }) }, + checkPopValid: function() { + return this.startDate < this.endDate + }, + + validatePop: function() { + if (!!this.startDate && !!this.endDate) { + // only want to update popValid and showPopError if both dates are filled in + this.popValid = this.checkPopValid() + this.showPopError = !this.popValid + } + + emitEvent('field-change', this, { + name: POP, + valid: this.checkPopValid(), + }) + }, + handleFieldChange: function(event) { if (this._uid === event.parent_uid) { if (event.name.includes(JEDI_CLIN_TYPE)) { @@ -78,6 +123,12 @@ export default { } else if (event.name.includes(OBLIGATED_AMOUNT)) { this.amount = parseFloat(event.value) this.clinChangeEvent() + } else if (event.name.includes(START_DATE)) { + if (!!event.value) this.startDate = new Date(event.value) + this.validatePop() + } else if (event.name.includes(END_DATE)) { + if (!!event.value) this.endDate = new Date(event.value) + this.validatePop() } } }, diff --git a/js/components/date_selector.js b/js/components/date_selector.js index 02466fb6..8e8f5327 100644 --- a/js/components/date_selector.js +++ b/js/components/date_selector.js @@ -51,18 +51,24 @@ export default { month(newMonth, oldMonth) { if (!!newMonth && newMonth.length > 2) { this.month = oldMonth + } else { + this.month = newMonth } }, day(newDay, oldDay) { if (!!newDay && newDay.length > 2) { this.day = oldDay + } else { + this.day = newDay } }, year(newYear, oldYear) { if (!!newYear && newYear.length > 4) { this.year = oldYear + } else { + this.year = newYear } }, }, @@ -96,7 +102,7 @@ export default { isYearValid: function() { // Emit a change event var valid = parseInt(this.year) >= 1 - // this._emitChange('year', this.year, valid) + this._emitChange('year', this.year, valid) return valid }, @@ -154,9 +160,8 @@ export default { methods: { onInput: function(e) { - console.log('emitting event') emitEvent('field-change', this, { - value: e.target.value, + value: this.formattedDate, name: this.name, watch: this.watch, valid: this.isDateValid, diff --git a/templates/components/date_picker.html b/templates/components/date_picker.html index 6924eddc..61c1889f 100644 --- a/templates/components/date_picker.html +++ b/templates/components/date_picker.html @@ -44,6 +44,7 @@ type="number" v-bind:class="{ 'usa-input-error': (month && !isMonthValid) }" v-model="month" + v-on:change="onInput" /> @@ -79,12 +80,6 @@ {{ Icon("ok", classes="icon--green") }} - -
diff --git a/templates/task_orders/step_3.html b/templates/task_orders/step_3.html index f1c3d115..76e6b6a6 100644 --- a/templates/task_orders/step_3.html +++ b/templates/task_orders/step_3.html @@ -50,6 +50,8 @@ v-bind:initial-loa-count="{{ fields.loas.data | length or 0 }}" v-bind:initial-clin-type="'{{ fields.jedi_clin_type.data }}'" v-bind:initial-amount='{{ fields.obligated_amount.data or 0 }}' + v-bind:initial-start-date="'{{ fields.start_date.data | string }}'" + v-bind:initial-end-date="'{{ fields.end_date.data | string }}'" {% else %} v-bind:initial-clin-index='clinIndex' v-bind:initial-clin-type="'JEDI_CLIN_1'" @@ -138,14 +140,15 @@Not sure how to describe your scope? Read some examples to get some inspiration.
' scope_label: Cloud project scope + start_date_error: PoP start date must be before end date. start_date_label: Start of period of performance (PoP) team_experience: built_1: Built, migrated, or consulted on 1-2 applications