diff --git a/alcs-frontend/src/app/features/application/applicant-info/application-details/application-details.component.spec.ts b/alcs-frontend/src/app/features/application/applicant-info/application-details/application-details.component.spec.ts index 763c225ebd..308b692cf4 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/application-details/application-details.component.spec.ts +++ b/alcs-frontend/src/app/features/application/applicant-info/application-details/application-details.component.spec.ts @@ -101,6 +101,13 @@ describe('ApplicationDetailsComponent', () => { soilHasSubmittedNotice: null, soilIsExtractionOrMining: null, soilIsFollowUp: null, + soilIsNewStructure: null, + soilStructureFarmUseReason: null, + soilStructureResidentialUseReason: null, + soilAgriParcelActivity: null, + soilStructureResidentialAccessoryUseReason: null, + soilStructureOtherUseReason: null, + soilProposedStructures: [], soilFollowUpIDs: null, soilProjectDuration: null, soilReduceNegativeImpacts: null, diff --git a/alcs-frontend/src/app/features/application/applicant-info/application-details/pfrs-details/pfrs-details.component.html b/alcs-frontend/src/app/features/application/applicant-info/application-details/pfrs-details/pfrs-details.component.html index e26a33bfdf..374bb61354 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/application-details/pfrs-details/pfrs-details.component.html +++ b/alcs-frontend/src/app/features/application/applicant-info/application-details/pfrs-details/pfrs-details.component.html @@ -1,4 +1,12 @@
+
Are you removing soil and placing fill in order to build a structure?
+
+ + {{ _applicationSubmission.soilIsNewStructure ? 'Yes' : 'No' }} + + +
+
Has the ALC previously received an application or Notice of Intent for this proposal?
@@ -120,13 +128,6 @@
-
- What alternative measures have you considered or attempted before proposing to place fill? -
-
- {{ _applicationSubmission.soilAlternativeMeasures }} -
-
Describe the type, origin and quality of fill proposed to be placed.
{{ _applicationSubmission.soilFillTypeToPlace }} @@ -136,10 +137,92 @@
{{ _applicationSubmission.soilTypeRemoved }}
-
What steps will be taken to reduce impacts to surrounding agricultural land?
-
- {{ _applicationSubmission.soilReduceNegativeImpacts }} -
+ + +
The total floor area (m2) for each of the proposed structure(s)
+
+
#
+
Type
+
Area
+ +
+ {{ i + 1 }} +
+
+ {{ mapStructureTypeValueToLabel(structure.type) }} + +
+
+ {{ structure.area }} m2 + +
+
+
+
+ +
+ + +
Describe how the structure is necessary for farm use
+
+ {{ _applicationSubmission.soilStructureFarmUseReason }} + +
+
+ + +
+ Describe why placing fill/removing soil is required for the residential structure(s) +
+
+ {{ _applicationSubmission.soilStructureResidentialUseReason }} + +
+
+ + +
Describe the current or proposed agricultural activity on the parcel(s)
+
+ {{ _applicationSubmission.soilAgriParcelActivity }} + +
+
+ + +
+ Describe the intended use of the residential accessory structure(s) and why placing fill/removing soil is + required +
+
+ {{ _applicationSubmission.soilStructureResidentialAccessoryUseReason }} + +
+
+ + +
+ Describe the intended use of the 'Other' structure(s) and why placing fill/removing soil is required +
+
+ {{ _applicationSubmission.soilStructureOtherUseReason }} + +
+
+
+ + +
+ What alternative measures have you considered or attempted before proposing to place fill? +
+
+ {{ _applicationSubmission.soilAlternativeMeasures }} +
+ +
What steps will be taken to reduce impacts to surrounding agricultural land?
+
+ {{ _applicationSubmission.soilReduceNegativeImpacts }} +
+
Proposal Map / Site Plan
@@ -147,41 +230,57 @@ {{ file.fileName }}
-
Cross Sections
-
-
- + + +
Cross Sections
+
+ +
Reclamation Plan
+ -
-
Reclamation Plan
- + -
Is your proposal for aggregate extraction or placer mining?
-
- - {{ _applicationSubmission.soilIsExtractionOrMining ? 'Yes' : 'No' }} - -
+ +
Detailed Building Plan(s)
+ +
-
- Have you submitted a Notice of Work to the Ministry of Energy, Mines and Low Carbon Innovation (EMLI)? -
-
- - {{ _applicationSubmission.soilHasSubmittedNotice ? 'Yes' : 'No' }} - -
+ +
Is your proposal for aggregate extraction or placer mining?
+
+ + {{ _applicationSubmission.soilIsExtractionOrMining ? 'Yes' : 'No' }} + +
-
Notice of Work
- +
+ Have you submitted a Notice of Work to the Ministry of Energy, Mines and Low Carbon Innovation (EMLI)? +
+
+ + {{ _applicationSubmission.soilHasSubmittedNotice ? 'Yes' : 'No' }} + +
+ +
Notice of Work
+ +
diff --git a/alcs-frontend/src/app/features/application/applicant-info/application-details/pfrs-details/pfrs-details.component.scss b/alcs-frontend/src/app/features/application/applicant-info/application-details/pfrs-details/pfrs-details.component.scss index f4efa4f475..63d243debd 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/application-details/pfrs-details/pfrs-details.component.scss +++ b/alcs-frontend/src/app/features/application/applicant-info/application-details/pfrs-details/pfrs-details.component.scss @@ -9,3 +9,11 @@ height: 16px; } } + +.structure-table { + display: grid; + grid-template-columns: max-content max-content max-content; + overflow-x: auto; + grid-column-gap: 36px; + grid-row-gap: 12px; +} diff --git a/alcs-frontend/src/app/features/application/applicant-info/application-details/pfrs-details/pfrs-details.component.ts b/alcs-frontend/src/app/features/application/applicant-info/application-details/pfrs-details/pfrs-details.component.ts index 88e9a6284e..f116acaa11 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/application-details/pfrs-details/pfrs-details.component.ts +++ b/alcs-frontend/src/app/features/application/applicant-info/application-details/pfrs-details/pfrs-details.component.ts @@ -4,6 +4,8 @@ import { ApplicationDocumentDto } from '../../../../../services/application/appl import { ApplicationDocumentService } from '../../../../../services/application/application-document/application-document.service'; import { ApplicationSubmissionDto } from '../../../../../services/application/application.dto'; import { DOCUMENT_TYPE } from '../../../../../shared/document/document.dto'; +import { STRUCTURE_TYPES } from '../../../../../services/notice-of-intent/notice-of-intent.dto'; +import { STRUCTURE_TYPE_LABEL_MAP } from '../../../../notice-of-intent/applicant-info/notice-of-intent-details/additional-information/additional-information.component'; @Component({ selector: 'app-pfrs-details[applicationSubmission]', @@ -11,10 +13,35 @@ import { DOCUMENT_TYPE } from '../../../../../shared/document/document.dto'; styleUrls: ['./pfrs-details.component.scss'], }) export class PfrsDetailsComponent { + isSoilStructureFarmUseReasonVisible = false; + isSoilStructureResidentialUseReasonVisible = false; + isSoilAgriParcelActivityVisible = false; + isSoilStructureResidentialAccessoryUseReasonVisible = false; + isSoilOtherStructureVisible = false; + _applicationSubmission: ApplicationSubmissionDto | undefined; @Input() set applicationSubmission(application: ApplicationSubmissionDto | undefined) { if (application) { this._applicationSubmission = application; + + this.isSoilStructureFarmUseReasonVisible = application.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.FARM_STRUCTURE, + ); + this.isSoilStructureResidentialUseReasonVisible = application.soilProposedStructures.some( + (structure) => + structure.type === STRUCTURE_TYPES.PRINCIPAL_RESIDENCE || + structure.type === STRUCTURE_TYPES.ADDITIONAL_RESIDENCE || + structure.type === STRUCTURE_TYPES.ACCESSORY_STRUCTURE, + ); + this.isSoilAgriParcelActivityVisible = application.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.FARM_STRUCTURE, + ); + this.isSoilStructureResidentialAccessoryUseReasonVisible = application.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.ACCESSORY_STRUCTURE, + ); + this.isSoilOtherStructureVisible = application.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.OTHER, + ); } } @@ -23,6 +50,7 @@ export class PfrsDetailsComponent { this.crossSections = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.CROSS_SECTIONS); this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); this.reclamationPlans = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.RECLAMATION_PLAN); + this.buildingPlans = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.BUILDING_PLAN); this.noticeOfWork = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.NOTICE_OF_WORK); } } @@ -30,6 +58,7 @@ export class PfrsDetailsComponent { crossSections: ApplicationDocumentDto[] = []; proposalMap: ApplicationDocumentDto[] = []; reclamationPlans: ApplicationDocumentDto[] = []; + buildingPlans: ApplicationDocumentDto[] = []; noticeOfWork: ApplicationDocumentDto[] = []; constructor(private router: Router, private applicationDocumentService: ApplicationDocumentService) {} @@ -37,4 +66,12 @@ export class PfrsDetailsComponent { async openFile(file: ApplicationDocumentDto) { await this.applicationDocumentService.download(file.uuid, file.fileName); } + + mapStructureTypeValueToLabel(value: STRUCTURE_TYPES | null): string | null { + if (value === null) { + return null; + } + + return STRUCTURE_TYPE_LABEL_MAP[value]; + } } diff --git a/alcs-frontend/src/app/features/application/applicant-info/application-details/pofo-details/pofo-details.component.html b/alcs-frontend/src/app/features/application/applicant-info/application-details/pofo-details/pofo-details.component.html index 0d22a0273f..563e0dbb4a 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/application-details/pofo-details/pofo-details.component.html +++ b/alcs-frontend/src/app/features/application/applicant-info/application-details/pofo-details/pofo-details.component.html @@ -1,4 +1,12 @@
+
Are you removing soil and placing fill in order to build a structure?
+
+ + {{ _applicationSubmission.soilIsNewStructure ? 'Yes' : 'No' }} + + +
+
Has the ALC previously received an application or Notice of Intent for this proposal?
@@ -70,21 +78,96 @@ m
-
- What alternative measures have you considered or attempted before proposing to place fill? -
-
- {{ _applicationSubmission.soilAlternativeMeasures }} -
-
Describe the type, origin and quality of fill proposed to be placed.
{{ _applicationSubmission.soilFillTypeToPlace }}
-
What steps will be taken to reduce impacts to surrounding agricultural land?
-
- {{ _applicationSubmission.soilReduceNegativeImpacts }} -
+ + +
The total floor area (m2) for each of the proposed structure(s)
+
+
#
+
Type
+
Area
+ +
+ {{ i + 1 }} +
+
+ {{ mapStructureTypeValueToLabel(structure.type) }} + +
+
+ {{ structure.area }} m2 + +
+
+
+
+ +
+ + +
Describe how the structure is necessary for farm use
+
+ {{ _applicationSubmission.soilStructureFarmUseReason }} + +
+
+ + +
+ Describe why placing fill/removing soil is required for the residential structure(s) +
+
+ {{ _applicationSubmission.soilStructureResidentialUseReason }} + +
+
+ + +
Describe the current or proposed agricultural activity on the parcel(s)
+
+ {{ _applicationSubmission.soilAgriParcelActivity }} + +
+
+ + +
+ Describe the intended use of the residential accessory structure(s) and why placing fill/removing soil is + required +
+
+ {{ _applicationSubmission.soilStructureResidentialAccessoryUseReason }} + +
+
+ + +
+ Describe the intended use of the 'Other' structure(s) and why placing fill/removing soil is required +
+
+ {{ _applicationSubmission.soilStructureOtherUseReason }} + +
+
+
+ + +
+ What alternative measures have you considered or attempted before proposing to place fill? +
+
+ {{ _applicationSubmission.soilAlternativeMeasures }} +
+ +
What steps will be taken to reduce impacts to surrounding agricultural land?
+
+ {{ _applicationSubmission.soilReduceNegativeImpacts }} +
+
Proposal Map / Site Plan
@@ -92,16 +175,30 @@ {{ file.fileName }}
-
Cross Sections
-
- - {{ file.fileName }} - -
-
Reclamation Plan
-
- - {{ file.fileName }} - -
+ + +
Cross Sections
+ + +
Reclamation Plan
+ +
+ + +
Detailed Building Plan(s)
+ +
diff --git a/alcs-frontend/src/app/features/application/applicant-info/application-details/pofo-details/pofo-details.component.scss b/alcs-frontend/src/app/features/application/applicant-info/application-details/pofo-details/pofo-details.component.scss index e69de29bb2..8c01a936dc 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/application-details/pofo-details/pofo-details.component.scss +++ b/alcs-frontend/src/app/features/application/applicant-info/application-details/pofo-details/pofo-details.component.scss @@ -0,0 +1,7 @@ +.structure-table { + display: grid; + grid-template-columns: max-content max-content max-content; + overflow-x: auto; + grid-column-gap: 36px; + grid-row-gap: 12px; +} diff --git a/alcs-frontend/src/app/features/application/applicant-info/application-details/pofo-details/pofo-details.component.ts b/alcs-frontend/src/app/features/application/applicant-info/application-details/pofo-details/pofo-details.component.ts index 2b4f326bbc..0fb6cd6ff8 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/application-details/pofo-details/pofo-details.component.ts +++ b/alcs-frontend/src/app/features/application/applicant-info/application-details/pofo-details/pofo-details.component.ts @@ -4,6 +4,8 @@ import { ApplicationDocumentDto } from '../../../../../services/application/appl import { ApplicationDocumentService } from '../../../../../services/application/application-document/application-document.service'; import { ApplicationSubmissionDto } from '../../../../../services/application/application.dto'; import { DOCUMENT_TYPE } from '../../../../../shared/document/document.dto'; +import { STRUCTURE_TYPES } from '../../../../../services/notice-of-intent/notice-of-intent.dto'; +import { STRUCTURE_TYPE_LABEL_MAP } from '../../../../notice-of-intent/applicant-info/notice-of-intent-details/additional-information/additional-information.component'; @Component({ selector: 'app-pofo-details[applicationSubmission]', @@ -11,10 +13,35 @@ import { DOCUMENT_TYPE } from '../../../../../shared/document/document.dto'; styleUrls: ['./pofo-details.component.scss'], }) export class PofoDetailsComponent { + isSoilStructureFarmUseReasonVisible = false; + isSoilStructureResidentialUseReasonVisible = false; + isSoilAgriParcelActivityVisible = false; + isSoilStructureResidentialAccessoryUseReasonVisible = false; + isSoilOtherStructureVisible = false; + _applicationSubmission: ApplicationSubmissionDto | undefined; @Input() set applicationSubmission(application: ApplicationSubmissionDto | undefined) { if (application) { this._applicationSubmission = application; + + this.isSoilStructureFarmUseReasonVisible = application.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.FARM_STRUCTURE, + ); + this.isSoilStructureResidentialUseReasonVisible = application.soilProposedStructures.some( + (structure) => + structure.type === STRUCTURE_TYPES.PRINCIPAL_RESIDENCE || + structure.type === STRUCTURE_TYPES.ADDITIONAL_RESIDENCE || + structure.type === STRUCTURE_TYPES.ACCESSORY_STRUCTURE, + ); + this.isSoilAgriParcelActivityVisible = application.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.FARM_STRUCTURE, + ); + this.isSoilStructureResidentialAccessoryUseReasonVisible = application.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.ACCESSORY_STRUCTURE, + ); + this.isSoilOtherStructureVisible = application.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.OTHER, + ); } } @@ -23,16 +50,26 @@ export class PofoDetailsComponent { this.crossSections = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.CROSS_SECTIONS); this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); this.reclamationPlans = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.RECLAMATION_PLAN); + this.buildingPlans = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.BUILDING_PLAN); } } crossSections: ApplicationDocumentDto[] = []; proposalMap: ApplicationDocumentDto[] = []; reclamationPlans: ApplicationDocumentDto[] = []; + buildingPlans: ApplicationDocumentDto[] = []; constructor(private router: Router, private applicationDocumentService: ApplicationDocumentService) {} async openFile(file: ApplicationDocumentDto) { await this.applicationDocumentService.download(file.uuid, file.fileName); } + + mapStructureTypeValueToLabel(value: STRUCTURE_TYPES | null): string | null { + if (value === null) { + return null; + } + + return STRUCTURE_TYPE_LABEL_MAP[value]; + } } diff --git a/alcs-frontend/src/app/features/application/applicant-info/application-details/roso-details/roso-details.component.html b/alcs-frontend/src/app/features/application/applicant-info/application-details/roso-details/roso-details.component.html index 8ec3a2ec4c..20d9f7f457 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/application-details/roso-details/roso-details.component.html +++ b/alcs-frontend/src/app/features/application/applicant-info/application-details/roso-details/roso-details.component.html @@ -1,4 +1,12 @@
+
Are you removing soil and placing fill in order to build a structure?
+
+ + {{ _applicationSubmission.soilIsNewStructure ? 'Yes' : 'No' }} + + +
+
Has the ALC previously received an application or Notice of Intent for this proposal?
@@ -76,10 +84,85 @@
{{ _applicationSubmission.soilTypeRemoved }}
-
What steps will be taken to reduce impacts to surrounding agricultural land?
-
- {{ _applicationSubmission.soilReduceNegativeImpacts }} -
+ + +
The total floor area (m2) for each of the proposed structure(s)
+
+
#
+
Type
+
Area
+ +
+ {{ i + 1 }} +
+
+ {{ mapStructureTypeValueToLabel(structure.type) }} + +
+
+ {{ structure.area }} m2 + +
+
+
+
+ +
+ + +
Describe how the structure is necessary for farm use
+
+ {{ _applicationSubmission.soilStructureFarmUseReason }} + +
+
+ + +
+ Describe why placing fill/removing soil is required for the residential structure(s) +
+
+ {{ _applicationSubmission.soilStructureResidentialUseReason }} + +
+
+ + +
Describe the current or proposed agricultural activity on the parcel(s)
+
+ {{ _applicationSubmission.soilAgriParcelActivity }} + +
+
+ + +
+ Describe the intended use of the residential accessory structure(s) and why placing fill/removing soil is + required +
+
+ {{ _applicationSubmission.soilStructureResidentialAccessoryUseReason }} + +
+
+ + +
+ Describe the intended use of the 'Other' structure(s) and why placing fill/removing soil is required +
+
+ {{ _applicationSubmission.soilStructureOtherUseReason }} + +
+
+
+ + +
What steps will be taken to reduce impacts to surrounding agricultural land?
+
+ {{ _applicationSubmission.soilReduceNegativeImpacts }} +
+
Proposal Map / Site Plan
@@ -87,16 +170,30 @@ {{ file.fileName }}
-
Cross Sections
-
- - {{ file.fileName }} - -
-
Reclamation Plan
-
- - {{ file.fileName }} - -
+ + +
Cross Sections
+ + +
Reclamation Plan
+ +
+ + +
Detailed Building Plan(s)
+ +
diff --git a/alcs-frontend/src/app/features/application/applicant-info/application-details/roso-details/roso-details.component.scss b/alcs-frontend/src/app/features/application/applicant-info/application-details/roso-details/roso-details.component.scss index e69de29bb2..8c01a936dc 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/application-details/roso-details/roso-details.component.scss +++ b/alcs-frontend/src/app/features/application/applicant-info/application-details/roso-details/roso-details.component.scss @@ -0,0 +1,7 @@ +.structure-table { + display: grid; + grid-template-columns: max-content max-content max-content; + overflow-x: auto; + grid-column-gap: 36px; + grid-row-gap: 12px; +} diff --git a/alcs-frontend/src/app/features/application/applicant-info/application-details/roso-details/roso-details.component.ts b/alcs-frontend/src/app/features/application/applicant-info/application-details/roso-details/roso-details.component.ts index bd32944e31..355f600350 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/application-details/roso-details/roso-details.component.ts +++ b/alcs-frontend/src/app/features/application/applicant-info/application-details/roso-details/roso-details.component.ts @@ -4,6 +4,8 @@ import { ApplicationDocumentDto } from '../../../../../services/application/appl import { ApplicationDocumentService } from '../../../../../services/application/application-document/application-document.service'; import { ApplicationSubmissionDto } from '../../../../../services/application/application.dto'; import { DOCUMENT_TYPE } from '../../../../../shared/document/document.dto'; +import { STRUCTURE_TYPES } from '../../../../../services/notice-of-intent/notice-of-intent.dto'; +import { STRUCTURE_TYPE_LABEL_MAP } from '../../../../notice-of-intent/applicant-info/notice-of-intent-details/additional-information/additional-information.component'; @Component({ selector: 'app-roso-details[applicationSubmission]', @@ -11,10 +13,35 @@ import { DOCUMENT_TYPE } from '../../../../../shared/document/document.dto'; styleUrls: ['./roso-details.component.scss'], }) export class RosoDetailsComponent { + isSoilStructureFarmUseReasonVisible = false; + isSoilStructureResidentialUseReasonVisible = false; + isSoilAgriParcelActivityVisible = false; + isSoilStructureResidentialAccessoryUseReasonVisible = false; + isSoilOtherStructureVisible = false; + _applicationSubmission: ApplicationSubmissionDto | undefined; @Input() set applicationSubmission(application: ApplicationSubmissionDto | undefined) { if (application) { this._applicationSubmission = application; + + this.isSoilStructureFarmUseReasonVisible = application.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.FARM_STRUCTURE, + ); + this.isSoilStructureResidentialUseReasonVisible = application.soilProposedStructures.some( + (structure) => + structure.type === STRUCTURE_TYPES.PRINCIPAL_RESIDENCE || + structure.type === STRUCTURE_TYPES.ADDITIONAL_RESIDENCE || + structure.type === STRUCTURE_TYPES.ACCESSORY_STRUCTURE, + ); + this.isSoilAgriParcelActivityVisible = application.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.FARM_STRUCTURE, + ); + this.isSoilStructureResidentialAccessoryUseReasonVisible = application.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.ACCESSORY_STRUCTURE, + ); + this.isSoilOtherStructureVisible = application.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.OTHER, + ); } } @@ -23,16 +50,26 @@ export class RosoDetailsComponent { this.crossSections = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.CROSS_SECTIONS); this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); this.reclamationPlans = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.RECLAMATION_PLAN); + this.buildingPlans = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.BUILDING_PLAN); } } crossSections: ApplicationDocumentDto[] = []; proposalMap: ApplicationDocumentDto[] = []; reclamationPlans: ApplicationDocumentDto[] = []; + buildingPlans: ApplicationDocumentDto[] = []; constructor(private router: Router, private applicationDocumentService: ApplicationDocumentService) {} async openFile(file: ApplicationDocumentDto) { await this.applicationDocumentService.download(file.uuid, file.fileName); } + + mapStructureTypeValueToLabel(value: STRUCTURE_TYPES | null): string | null { + if (value === null) { + return null; + } + + return STRUCTURE_TYPE_LABEL_MAP[value]; + } } diff --git a/alcs-frontend/src/app/features/notice-of-intent/applicant-info/notice-of-intent-details/additional-information/additional-information.component.ts b/alcs-frontend/src/app/features/notice-of-intent/applicant-info/notice-of-intent-details/additional-information/additional-information.component.ts index fba6a14e39..e0687da116 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/applicant-info/notice-of-intent-details/additional-information/additional-information.component.ts +++ b/alcs-frontend/src/app/features/notice-of-intent/applicant-info/notice-of-intent-details/additional-information/additional-information.component.ts @@ -9,7 +9,7 @@ import { } from '../../../../../services/notice-of-intent/notice-of-intent.dto'; import { DOCUMENT_TYPE } from '../../../../../shared/document/document.dto'; -const NOI_STRUCTURE_TYPE_LABEL_MAP: Record = { +export const STRUCTURE_TYPE_LABEL_MAP: Record = { [STRUCTURE_TYPES.FARM_STRUCTURE]: STRUCTURE_TYPES.FARM_STRUCTURE, [STRUCTURE_TYPES.PRINCIPAL_RESIDENCE]: 'Principal Residence', [STRUCTURE_TYPES.ADDITIONAL_RESIDENCE]: 'Additional Residence', @@ -96,6 +96,6 @@ export class AdditionalInformationComponent { return null; } - return NOI_STRUCTURE_TYPE_LABEL_MAP[value]; + return STRUCTURE_TYPE_LABEL_MAP[value]; } } diff --git a/alcs-frontend/src/app/services/application/application-submission/application-submission.service.spec.ts b/alcs-frontend/src/app/services/application/application-submission/application-submission.service.spec.ts index e26b0d4ad1..9568259950 100644 --- a/alcs-frontend/src/app/services/application/application-submission/application-submission.service.spec.ts +++ b/alcs-frontend/src/app/services/application/application-submission/application-submission.service.spec.ts @@ -91,6 +91,13 @@ describe('ApplicationSubmissionService', () => { soilAlternativeMeasures: null, soilHasSubmittedNotice: null, soilIsExtractionOrMining: null, + soilIsNewStructure: null, + soilStructureFarmUseReason: null, + soilStructureResidentialUseReason: null, + soilAgriParcelActivity: null, + soilStructureResidentialAccessoryUseReason: null, + soilStructureOtherUseReason: null, + soilProposedStructures: [], soilIsFollowUp: null, soilFollowUpIDs: null, soilProjectDuration: null, diff --git a/alcs-frontend/src/app/services/application/application.dto.ts b/alcs-frontend/src/app/services/application/application.dto.ts index 9fe3f94b7e..e6e5f4ebd0 100644 --- a/alcs-frontend/src/app/services/application/application.dto.ts +++ b/alcs-frontend/src/app/services/application/application.dto.ts @@ -1,6 +1,7 @@ import { BaseCodeDto } from '../../shared/dto/base.dto'; import { SYSTEM_SOURCE_TYPES } from '../../shared/dto/system-source.types.dto'; import { CardDto } from '../card/card.dto'; +import { ProposedStructure } from '../notice-of-intent/notice-of-intent.dto'; import { UserDto } from '../user/user.dto'; import { ApplicationRegionDto, ApplicationTypeDto } from './application-code.dto'; import { ApplicationLocalGovernmentDto } from './application-local-government/application-local-government.dto'; @@ -171,6 +172,7 @@ export interface ApplicationSubmissionDto { subdProposedLots: ProposedLot[]; //Soil Fields + soilIsNewStructure: boolean | null; soilIsFollowUp: boolean | null; soilFollowUpIDs: string | null; soilTypeRemoved: string | null; @@ -197,6 +199,12 @@ export interface ApplicationSubmissionDto { soilAlternativeMeasures: string | null; soilIsExtractionOrMining: boolean | null; soilHasSubmittedNotice: boolean | null; + soilStructureFarmUseReason: string | null; + soilStructureResidentialUseReason: string | null; + soilAgriParcelActivity: string | null; + soilStructureResidentialAccessoryUseReason: string | null; + soilStructureOtherUseReason: string | null; + soilProposedStructures: ProposedStructure[]; //NARU Fields naruWillBeOverFiveHundredM2: boolean | null; diff --git a/portal-frontend/src/app/features/applications/application-details/pfrs-details/pfrs-details.component.html b/portal-frontend/src/app/features/applications/application-details/pfrs-details/pfrs-details.component.html index cb7f40503e..6cbbab13f8 100644 --- a/portal-frontend/src/app/features/applications/application-details/pfrs-details/pfrs-details.component.html +++ b/portal-frontend/src/app/features/applications/application-details/pfrs-details/pfrs-details.component.html @@ -1,4 +1,12 @@
+
Are you removing soil and placing fill in order to build a structure?
+
+ + {{ _applicationSubmission.soilIsNewStructure ? 'Yes' : 'No' }} + + +
+
Has the ALC previously received an application or Notice of Intent for this proposal?
@@ -193,19 +201,115 @@
-
- What alternative measures have you considered or attempted before proposing to place fill? -
-
- {{ _applicationSubmission.soilAlternativeMeasures }} - -
+ +
The total floor area (m2) for each of the proposed structure(s)
+
+
#
+
Type
+
Area
+ +
+ {{ i + 1 }} +
+
+ {{ mapStructureTypeValueToLabel(structure.type) }} + +
+
+ {{ structure.area }} m2 + +
+
+
+ + + + +
+ +
-
What steps will be taken to reduce impacts to surrounding agricultural land?
-
- {{ _applicationSubmission.soilReduceNegativeImpacts }} - -
+ +
Describe how the structure is necessary for farm use
+
+ {{ _applicationSubmission.soilStructureFarmUseReason }} + +
+
+ + +
+ Describe why placing fill/removing soil is required for the residential structure(s) +
+
+ {{ _applicationSubmission.soilStructureResidentialUseReason }} + +
+
+ + +
Describe the current or proposed agricultural activity on the parcel(s)
+
+ {{ _applicationSubmission.soilAgriParcelActivity }} + +
+
+ + +
+ Describe the intended use of the residential accessory structure(s) and why placing fill/removing soil is + required +
+
+ {{ _applicationSubmission.soilStructureResidentialAccessoryUseReason }} + +
+
+ + +
+ Describe the intended use of the 'Other' structure(s) and why placing fill/removing soil is required +
+
+ {{ _applicationSubmission.soilStructureOtherUseReason }} + +
+
+
+ + +
+ What alternative measures have you considered or attempted before proposing to place fill? +
+
+ {{ _applicationSubmission.soilAlternativeMeasures }} + +
+ +
What steps will be taken to reduce impacts to surrounding agricultural land?
+
+ {{ _applicationSubmission.soilReduceNegativeImpacts }} + +
+
Proposal Map / Site Plan
@@ -215,53 +319,67 @@
-
Cross Sections
- + +
Cross Sections
+ -
Reclamation Plan
- +
Reclamation Plan
+ +
-
Is your proposal for aggregate extraction or placer mining?
-
- - {{ _applicationSubmission.soilIsExtractionOrMining ? 'Yes' : 'No' }} - - -
+ +
Detailed Building Plan(s)
+ +
-
- Have you submitted a Notice of Work to the Ministry of Energy, Mines and Low Carbon Innovation (EMLI)? -
-
- - {{ _applicationSubmission.soilHasSubmittedNotice ? 'Yes' : 'No' }} - - -
+ +
Is your proposal for aggregate extraction or placer mining?
+
+ + {{ _applicationSubmission.soilIsExtractionOrMining ? 'Yes' : 'No' }} + + +
-
Notice of Work
- +
+ Have you submitted a Notice of Work to the Ministry of Energy, Mines and Low Carbon Innovation (EMLI)? +
+
+ + {{ _applicationSubmission.soilHasSubmittedNotice ? 'Yes' : 'No' }} + + +
+ +
Notice of Work
+ +
diff --git a/portal-frontend/src/app/features/applications/application-details/pfrs-details/pfrs-details.component.scss b/portal-frontend/src/app/features/applications/application-details/pfrs-details/pfrs-details.component.scss index 36aafed7e7..5a971346c5 100644 --- a/portal-frontend/src/app/features/applications/application-details/pfrs-details/pfrs-details.component.scss +++ b/portal-frontend/src/app/features/applications/application-details/pfrs-details/pfrs-details.component.scss @@ -21,3 +21,41 @@ height: rem(16); } } + +.structure-table { + display: grid; + grid-template-columns: max-content max-content max-content; + overflow-x: auto; + grid-column-gap: rem(36); + grid-row-gap: rem(12); + + @media screen and (min-width: $tabletBreakpoint) { + grid-template-columns: 0.55fr 1fr 1fr; + } + + @media screen and (min-width: $midBreakpoint) { + grid-template-columns: 1fr 1fr 2fr; + } +} + +.mobile-structure-card { + width: 100%; + box-shadow: none; + border: none; + border-radius: 0; + word-wrap: break-word; + white-space: normal; +} + +.mobile-structure-card-border { + border-top: rem(1) solid #aaaaaa; +} + +.mobile-structure-title { + display: block; + margin: 0; +} + +.mobile-structure-label { + margin: rem(5) 0 rem(5) 0; +} diff --git a/portal-frontend/src/app/features/applications/application-details/pfrs-details/pfrs-details.component.ts b/portal-frontend/src/app/features/applications/application-details/pfrs-details/pfrs-details.component.ts index df615202ef..1c24317ccd 100644 --- a/portal-frontend/src/app/features/applications/application-details/pfrs-details/pfrs-details.component.ts +++ b/portal-frontend/src/app/features/applications/application-details/pfrs-details/pfrs-details.component.ts @@ -5,6 +5,11 @@ import { ApplicationDocumentService } from '../../../../services/application-doc import { ApplicationSubmissionDetailedDto } from '../../../../services/application-submission/application-submission.dto'; import { DOCUMENT_TYPE } from '../../../../shared/dto/document.dto'; import { openFileInline } from '../../../../shared/utils/file'; +import { MOBILE_BREAKPOINT } from '../../../../shared/utils/breakpoints'; +import { + STRUCTURE_TYPE_LABEL_MAP, + STRUCTURE_TYPES, +} from '../../../notice-of-intents/edit-submission/additional-information/additional-information.component'; @Component({ selector: 'app-pfrs-details[applicationSubmission]', @@ -16,11 +21,38 @@ export class PfrsDetailsComponent { @Input() showEdit = true; @Input() draftMode = false; + isMobile = window.innerWidth <= MOBILE_BREAKPOINT; + + isSoilStructureFarmUseReasonVisible = false; + isSoilStructureResidentialUseReasonVisible = false; + isSoilAgriParcelActivityVisible = false; + isSoilStructureResidentialAccessoryUseReasonVisible = false; + isSoilOtherStructureVisible = false; + _applicationSubmission: ApplicationSubmissionDetailedDto | undefined; @Input() set applicationSubmission(applicationSubmission: ApplicationSubmissionDetailedDto | undefined) { if (applicationSubmission) { this._applicationSubmission = applicationSubmission; + + this.isSoilStructureFarmUseReasonVisible = applicationSubmission.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.FARM_STRUCTURE, + ); + this.isSoilStructureResidentialUseReasonVisible = applicationSubmission.soilProposedStructures.some( + (structure) => + structure.type === STRUCTURE_TYPES.PRINCIPAL_RESIDENCE || + structure.type === STRUCTURE_TYPES.ADDITIONAL_RESIDENCE || + structure.type === STRUCTURE_TYPES.ACCESSORY_STRUCTURE, + ); + this.isSoilAgriParcelActivityVisible = applicationSubmission.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.FARM_STRUCTURE, + ); + this.isSoilStructureResidentialAccessoryUseReasonVisible = applicationSubmission.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.ACCESSORY_STRUCTURE, + ); + this.isSoilOtherStructureVisible = applicationSubmission.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.OTHER_STRUCTURE, + ); } } @@ -28,12 +60,14 @@ export class PfrsDetailsComponent { this.crossSections = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.CROSS_SECTIONS); this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); this.reclamationPlans = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.RECLAMATION_PLAN); + this.buildingPlans = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.BUILDING_PLAN); this.noticeOfWork = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.NOTICE_OF_WORK); } crossSections: ApplicationDocumentDto[] = []; proposalMap: ApplicationDocumentDto[] = []; reclamationPlans: ApplicationDocumentDto[] = []; + buildingPlans: ApplicationDocumentDto[] = []; noticeOfWork: ApplicationDocumentDto[] = []; constructor(private router: Router, private applicationDocumentService: ApplicationDocumentService) {} @@ -54,4 +88,12 @@ export class PfrsDetailsComponent { openFileInline(res.url, file.fileName); } } + + mapStructureTypeValueToLabel(value: STRUCTURE_TYPES | null): string | null { + if (value === null) { + return null; + } + + return STRUCTURE_TYPE_LABEL_MAP[value]; + } } diff --git a/portal-frontend/src/app/features/applications/application-details/pofo-details/pofo-details.component.html b/portal-frontend/src/app/features/applications/application-details/pofo-details/pofo-details.component.html index 4218d96047..351ece46a8 100644 --- a/portal-frontend/src/app/features/applications/application-details/pofo-details/pofo-details.component.html +++ b/portal-frontend/src/app/features/applications/application-details/pofo-details/pofo-details.component.html @@ -1,4 +1,12 @@
+
Are you removing soil and placing fill in order to build a structure?
+
+ + {{ _applicationSubmission.soilIsNewStructure ? 'Yes' : 'No' }} + + +
+
Has the ALC previously received an application or Notice of Intent for this proposal?
@@ -117,19 +125,115 @@
-
- What alternative measures have you considered or attempted before proposing to place fill? -
-
- {{ _applicationSubmission.soilAlternativeMeasures }} - -
+ +
The total floor area (m2) for each of the proposed structure(s)
+
+
#
+
Type
+
Area
+ +
+ {{ i + 1 }} +
+
+ {{ mapStructureTypeValueToLabel(structure.type) }} + +
+
+ {{ structure.area }} m2 + +
+
+
+ + + + +
+ +
-
What steps will be taken to reduce impacts to surrounding agricultural land?
-
- {{ _applicationSubmission.soilReduceNegativeImpacts }} - -
+ +
Describe how the structure is necessary for farm use
+
+ {{ _applicationSubmission.soilStructureFarmUseReason }} + +
+
+ + +
+ Describe why placing fill/removing soil is required for the residential structure(s) +
+
+ {{ _applicationSubmission.soilStructureResidentialUseReason }} + +
+
+ + +
Describe the current or proposed agricultural activity on the parcel(s)
+
+ {{ _applicationSubmission.soilAgriParcelActivity }} + +
+
+ + +
+ Describe the intended use of the residential accessory structure(s) and why placing fill/removing soil is + required +
+
+ {{ _applicationSubmission.soilStructureResidentialAccessoryUseReason }} + +
+
+ + +
+ Describe the intended use of the 'Other' structure(s) and why placing fill/removing soil is required +
+
+ {{ _applicationSubmission.soilStructureOtherUseReason }} + +
+
+
+ + +
+ What alternative measures have you considered or attempted before proposing to place fill? +
+
+ {{ _applicationSubmission.soilAlternativeMeasures }} + +
+ +
What steps will be taken to reduce impacts to surrounding agricultural land?
+
+ {{ _applicationSubmission.soilReduceNegativeImpacts }} + +
+
Proposal Map / Site Plan
@@ -139,21 +243,33 @@
-
Cross Sections
- + +
Cross Sections
+ -
Reclamation Plan
- +
Reclamation Plan
+ +
+ + +
Detailed Building Plan(s)
+ +
diff --git a/portal-frontend/src/app/features/applications/application-details/pofo-details/pofo-details.component.scss b/portal-frontend/src/app/features/applications/application-details/pofo-details/pofo-details.component.scss index 63cfeaa16b..5d7b57d09e 100644 --- a/portal-frontend/src/app/features/applications/application-details/pofo-details/pofo-details.component.scss +++ b/portal-frontend/src/app/features/applications/application-details/pofo-details/pofo-details.component.scss @@ -16,3 +16,41 @@ grid-column-gap: rem(16); } } + +.structure-table { + display: grid; + grid-template-columns: max-content max-content max-content; + overflow-x: auto; + grid-column-gap: rem(36); + grid-row-gap: rem(12); + + @media screen and (min-width: $tabletBreakpoint) { + grid-template-columns: 0.55fr 1fr 1fr; + } + + @media screen and (min-width: $midBreakpoint) { + grid-template-columns: 1fr 1fr 2fr; + } +} + +.mobile-structure-card { + width: 100%; + box-shadow: none; + border: none; + border-radius: 0; + word-wrap: break-word; + white-space: normal; +} + +.mobile-structure-card-border { + border-top: rem(1) solid #aaaaaa; +} + +.mobile-structure-title { + display: block; + margin: 0; +} + +.mobile-structure-label { + margin: rem(5) 0 rem(5) 0; +} diff --git a/portal-frontend/src/app/features/applications/application-details/pofo-details/pofo-details.component.ts b/portal-frontend/src/app/features/applications/application-details/pofo-details/pofo-details.component.ts index 7e6efd5432..0eb619040e 100644 --- a/portal-frontend/src/app/features/applications/application-details/pofo-details/pofo-details.component.ts +++ b/portal-frontend/src/app/features/applications/application-details/pofo-details/pofo-details.component.ts @@ -5,6 +5,11 @@ import { ApplicationDocumentService } from '../../../../services/application-doc import { ApplicationSubmissionDetailedDto } from '../../../../services/application-submission/application-submission.dto'; import { DOCUMENT_TYPE } from '../../../../shared/dto/document.dto'; import { openFileInline } from '../../../../shared/utils/file'; +import { MOBILE_BREAKPOINT } from '../../../../shared/utils/breakpoints'; +import { + STRUCTURE_TYPE_LABEL_MAP, + STRUCTURE_TYPES, +} from '../../../notice-of-intents/edit-submission/additional-information/additional-information.component'; @Component({ selector: 'app-pofo-details[applicationSubmission]', @@ -16,11 +21,38 @@ export class PofoDetailsComponent { @Input() showEdit = true; @Input() draftMode = false; + isMobile = window.innerWidth <= MOBILE_BREAKPOINT; + + isSoilStructureFarmUseReasonVisible = false; + isSoilStructureResidentialUseReasonVisible = false; + isSoilAgriParcelActivityVisible = false; + isSoilStructureResidentialAccessoryUseReasonVisible = false; + isSoilOtherStructureVisible = false; + _applicationSubmission: ApplicationSubmissionDetailedDto | undefined; @Input() set applicationSubmission(applicationSubmission: ApplicationSubmissionDetailedDto | undefined) { if (applicationSubmission) { this._applicationSubmission = applicationSubmission; + + this.isSoilStructureFarmUseReasonVisible = applicationSubmission.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.FARM_STRUCTURE, + ); + this.isSoilStructureResidentialUseReasonVisible = applicationSubmission.soilProposedStructures.some( + (structure) => + structure.type === STRUCTURE_TYPES.PRINCIPAL_RESIDENCE || + structure.type === STRUCTURE_TYPES.ADDITIONAL_RESIDENCE || + structure.type === STRUCTURE_TYPES.ACCESSORY_STRUCTURE, + ); + this.isSoilAgriParcelActivityVisible = applicationSubmission.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.FARM_STRUCTURE, + ); + this.isSoilStructureResidentialAccessoryUseReasonVisible = applicationSubmission.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.ACCESSORY_STRUCTURE, + ); + this.isSoilOtherStructureVisible = applicationSubmission.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.OTHER_STRUCTURE, + ); } } @@ -28,11 +60,13 @@ export class PofoDetailsComponent { this.crossSections = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.CROSS_SECTIONS); this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); this.reclamationPlans = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.RECLAMATION_PLAN); + this.buildingPlans = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.BUILDING_PLAN); } crossSections: ApplicationDocumentDto[] = []; proposalMap: ApplicationDocumentDto[] = []; reclamationPlans: ApplicationDocumentDto[] = []; + buildingPlans: ApplicationDocumentDto[] = []; constructor(private router: Router, private applicationDocumentService: ApplicationDocumentService) {} @@ -52,4 +86,12 @@ export class PofoDetailsComponent { openFileInline(res.url, file.fileName); } } + + mapStructureTypeValueToLabel(value: STRUCTURE_TYPES | null): string | null { + if (value === null) { + return null; + } + + return STRUCTURE_TYPE_LABEL_MAP[value]; + } } diff --git a/portal-frontend/src/app/features/applications/application-details/roso-details/roso-details.component.html b/portal-frontend/src/app/features/applications/application-details/roso-details/roso-details.component.html index 083051454b..7917544694 100644 --- a/portal-frontend/src/app/features/applications/application-details/roso-details/roso-details.component.html +++ b/portal-frontend/src/app/features/applications/application-details/roso-details/roso-details.component.html @@ -1,4 +1,12 @@
+
Are you removing soil and placing fill in order to build a structure?
+
+ + {{ _applicationSubmission.soilIsNewStructure ? 'Yes' : 'No' }} + + +
+
Has the ALC previously received an application or Notice of Intent for this proposal?
@@ -117,11 +125,107 @@
-
What steps will be taken to reduce impacts to surrounding agricultural land?
-
- {{ _applicationSubmission.soilReduceNegativeImpacts }} - -
+ +
The total floor area (m2) for each of the proposed structure(s)
+
+
#
+
Type
+
Area
+ +
+ {{ i + 1 }} +
+
+ {{ mapStructureTypeValueToLabel(structure.type) }} + +
+
+ {{ structure.area }} m2 + +
+
+
+ + + + +
+ +
+ + +
Describe how the structure is necessary for farm use
+
+ {{ _applicationSubmission.soilStructureFarmUseReason }} + +
+
+ + +
+ Describe why placing fill/removing soil is required for the residential structure(s) +
+
+ {{ _applicationSubmission.soilStructureResidentialUseReason }} + +
+
+ + +
Describe the current or proposed agricultural activity on the parcel(s)
+
+ {{ _applicationSubmission.soilAgriParcelActivity }} + +
+
+ + +
+ Describe the intended use of the residential accessory structure(s) and why placing fill/removing soil is + required +
+
+ {{ _applicationSubmission.soilStructureResidentialAccessoryUseReason }} + +
+
+ + +
+ Describe the intended use of the 'Other' structure(s) and why placing fill/removing soil is required +
+
+ {{ _applicationSubmission.soilStructureOtherUseReason }} + +
+
+
+ + +
What steps will be taken to reduce impacts to surrounding agricultural land?
+
+ {{ _applicationSubmission.soilReduceNegativeImpacts }} + +
+
Proposal Map / Site Plan
@@ -131,21 +235,33 @@
-
Cross Sections
- + +
Cross Sections
+ -
Reclamation Plan
- +
Reclamation Plan
+ +
+ + +
Detailed Building Plan(s)
+ +
diff --git a/portal-frontend/src/app/features/applications/application-details/roso-details/roso-details.component.scss b/portal-frontend/src/app/features/applications/application-details/roso-details/roso-details.component.scss index 63cfeaa16b..5d7b57d09e 100644 --- a/portal-frontend/src/app/features/applications/application-details/roso-details/roso-details.component.scss +++ b/portal-frontend/src/app/features/applications/application-details/roso-details/roso-details.component.scss @@ -16,3 +16,41 @@ grid-column-gap: rem(16); } } + +.structure-table { + display: grid; + grid-template-columns: max-content max-content max-content; + overflow-x: auto; + grid-column-gap: rem(36); + grid-row-gap: rem(12); + + @media screen and (min-width: $tabletBreakpoint) { + grid-template-columns: 0.55fr 1fr 1fr; + } + + @media screen and (min-width: $midBreakpoint) { + grid-template-columns: 1fr 1fr 2fr; + } +} + +.mobile-structure-card { + width: 100%; + box-shadow: none; + border: none; + border-radius: 0; + word-wrap: break-word; + white-space: normal; +} + +.mobile-structure-card-border { + border-top: rem(1) solid #aaaaaa; +} + +.mobile-structure-title { + display: block; + margin: 0; +} + +.mobile-structure-label { + margin: rem(5) 0 rem(5) 0; +} diff --git a/portal-frontend/src/app/features/applications/application-details/roso-details/roso-details.component.ts b/portal-frontend/src/app/features/applications/application-details/roso-details/roso-details.component.ts index 03ca23a8db..f5507731b8 100644 --- a/portal-frontend/src/app/features/applications/application-details/roso-details/roso-details.component.ts +++ b/portal-frontend/src/app/features/applications/application-details/roso-details/roso-details.component.ts @@ -5,6 +5,11 @@ import { ApplicationDocumentService } from '../../../../services/application-doc import { ApplicationSubmissionDetailedDto } from '../../../../services/application-submission/application-submission.dto'; import { DOCUMENT_TYPE } from '../../../../shared/dto/document.dto'; import { openFileInline } from '../../../../shared/utils/file'; +import { MOBILE_BREAKPOINT } from '../../../../shared/utils/breakpoints'; +import { + STRUCTURE_TYPE_LABEL_MAP, + STRUCTURE_TYPES, +} from '../../../notice-of-intents/edit-submission/additional-information/additional-information.component'; @Component({ selector: 'app-roso-details[applicationSubmission]', @@ -16,11 +21,38 @@ export class RosoDetailsComponent { @Input() showEdit = true; @Input() draftMode = false; + isMobile = window.innerWidth <= MOBILE_BREAKPOINT; + + isSoilStructureFarmUseReasonVisible = false; + isSoilStructureResidentialUseReasonVisible = false; + isSoilAgriParcelActivityVisible = false; + isSoilStructureResidentialAccessoryUseReasonVisible = false; + isSoilOtherStructureVisible = false; + _applicationSubmission: ApplicationSubmissionDetailedDto | undefined; @Input() set applicationSubmission(applicationSubmission: ApplicationSubmissionDetailedDto | undefined) { if (applicationSubmission) { this._applicationSubmission = applicationSubmission; + + this.isSoilStructureFarmUseReasonVisible = applicationSubmission.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.FARM_STRUCTURE, + ); + this.isSoilStructureResidentialUseReasonVisible = applicationSubmission.soilProposedStructures.some( + (structure) => + structure.type === STRUCTURE_TYPES.PRINCIPAL_RESIDENCE || + structure.type === STRUCTURE_TYPES.ADDITIONAL_RESIDENCE || + structure.type === STRUCTURE_TYPES.ACCESSORY_STRUCTURE, + ); + this.isSoilAgriParcelActivityVisible = applicationSubmission.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.FARM_STRUCTURE, + ); + this.isSoilStructureResidentialAccessoryUseReasonVisible = applicationSubmission.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.ACCESSORY_STRUCTURE, + ); + this.isSoilOtherStructureVisible = applicationSubmission.soilProposedStructures.some( + (structure) => structure.type === STRUCTURE_TYPES.OTHER_STRUCTURE, + ); } } @@ -28,11 +60,13 @@ export class RosoDetailsComponent { this.crossSections = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.CROSS_SECTIONS); this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); this.reclamationPlans = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.RECLAMATION_PLAN); + this.buildingPlans = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.BUILDING_PLAN); } crossSections: ApplicationDocumentDto[] = []; proposalMap: ApplicationDocumentDto[] = []; reclamationPlans: ApplicationDocumentDto[] = []; + buildingPlans: ApplicationDocumentDto[] = []; constructor(private router: Router, private applicationDocumentService: ApplicationDocumentService) {} @@ -52,4 +86,12 @@ export class RosoDetailsComponent { openFileInline(res.url, file.fileName); } } + + mapStructureTypeValueToLabel(value: STRUCTURE_TYPES | null): string | null { + if (value === null) { + return null; + } + + return STRUCTURE_TYPE_LABEL_MAP[value]; + } } diff --git a/portal-frontend/src/app/features/applications/edit-submission/proposal/pfrs-proposal/pfrs-proposal.component.html b/portal-frontend/src/app/features/applications/edit-submission/proposal/pfrs-proposal/pfrs-proposal.component.html index a7d5aea6f7..15628501f5 100644 --- a/portal-frontend/src/app/features/applications/edit-submission/proposal/pfrs-proposal/pfrs-proposal.component.html +++ b/portal-frontend/src/app/features/applications/edit-submission/proposal/pfrs-proposal/pfrs-proposal.component.html @@ -23,8 +23,44 @@

Proposal

+
+
+ + Are you removing soil and placing fill in order to build a structure? + +
This can include farm buildings, residences, or accessory buildings.
+
+ + Yes + + No + + +
+ Note: The form will be updated with additional required questions if you are building a structure + +
+
Has the ALC previously received an application or Notice of Intent for this proposal? @@ -40,7 +76,7 @@

Proposal

Yes @@ -48,7 +84,7 @@

Proposal

No @@ -56,6 +92,7 @@

Proposal

+
If you have multiple IDs, please separate with a comma.
@@ -68,6 +105,7 @@

Proposal

This field is required
+
@@ -180,6 +218,7 @@

Proposal

(dataChange)="markDirty()" >
+
Of the proposed totals provided above, please input the dimensions of soil that has already been removed or @@ -254,64 +293,385 @@

Proposal

Example: Aggregate, Extraction, Placer Mining, Peat Extraction, Soil etc.
Characters left: {{ 4000 - soilTypeRemovedText.textLength }}
+
-
- -
- Applicants should provide evidence demonstrating that normal farm practices have been attempted prior to the - submission of this application to place fill. + + + Provide the total floor area (m2) for each of the proposed structure(s) +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#{{ i + 1 }}Type + + + + {{ type.label }} + + + +
+ warning +
+ This field is required +
+
+
Total Floor Area + + + m2 + +
+ warning +
+ This field is required +
+
+
Action + +
+
+
+ The proposed residential structure and its total floor area must be allowed under the ALC Act and/or + ALR Use Regulation. If not, you may require a 'Non-Adhering Residential Use' application instead. For + more info, please see + Housing in the ALR + on the ALC website. +
+
+
+ No Proposed Structures Entered. Use the button below to add your first structure. +
- - - -
- warning -
This field is required
+ + +
+
+ + + At least one structure is required +
- Example: Aggregate, Extraction, Placer Mining, Peat Extraction, Soil etc. -
Characters left: {{ 4000 - soilAlternativeMeasuresText.textLength }}
- - - - -
- warning -
This field is required
-
- - Example: Project phasing, providing landscape screening, fencing, buffering, erosion and sediment control, - temporary or permanent drainage, etc. - -
Characters left: {{ 4000 - reduceNegativeImpactsText.textLength }}
+ + Selected proposed structure type(s) will determine the proposal questions below +
+ + +
+ +
+ +
+ Please refer to + Farm Structures in the ALR + on the ALC website for more detail. +
+ + + +
+ warning +
This field is required
+
+
Characters left: {{ 4000 - soilStructureFarmUseReasonText.textLength }}
+
+ +
+ +
Include the area, yields, crop types, and farm equipment size and attachments
+ + + +
+ warning +
This field is required
+
+
Characters left: {{ 4000 - soilAgriParcelActivityText.textLength }}
+
+
+ + +
+ +
+ Please refer to + Housing in the ALR + on the ALC website for more detail. +
+ + + +
+ warning +
This field is required
+
+
Characters left: {{ 4000 - soilStructureResidentialUseReasonText.textLength }}
+
+
+ + +
+ +
+ Please refer to + Housing in the ALR + on the ALC website for more detail. +
+ + + +
+ warning +
This field is required
+
+
Characters left: {{ 4000 - structureResidentialAccessoryUseReasonText.textLength }}
+
+
+ + +
+ + + + +
+ warning +
This field is required
+
+
Characters left: {{ 4000 - soilStructureOtherUseReasonText.textLength }}
+
+
+ + +
+ +
+ Applicants should provide evidence demonstrating that normal farm practices have been attempted prior to the + submission of this application to place fill. +
+ + + +
+ warning +
This field is required
+
+ Example: Aggregate, Extraction, Placer Mining, Peat Extraction, Soil etc. +
Characters left: {{ 4000 - soilAlternativeMeasuresText.textLength }}
+
+ +
+ + + + +
+ warning +
This field is required
+
+ + Example: Project phasing, providing landscape screening, fencing, buffering, erosion and sediment control, + temporary or permanent drainage, etc. + +
Characters left: {{ 4000 - reduceNegativeImpactsText.textLength }}
+
+
+
Proposal Map / Site Plan
A visual representation of your proposal.
@@ -326,159 +686,184 @@

Proposal

[showVirusError]="showProposalMapVirus" >
-
- Cross Sections -
Include North-South and East-West cross sections
- - Please refer to - Removal of Soil & Placement of Fill - on the ALC website for more information - - -
-
- Reclamation Plan -
- The Reclamation Plan should be completed by a qualified Professional Agrologist and contain the area's - agricultural capability assessment. + + +
+ Cross Sections +
Include North-South and East-West cross sections
+ + Please refer to + Removal of Soil & Placement of Fill + on the ALC website for more information + +
- - Please refer to - Removal of Soil & Placement of Fill - on the ALC website for more information - - -
-
- Is your proposal for aggregate extraction or placer mining? -
- - Yes - - No - - +
+ Reclamation Plan +
+ The Reclamation Plan should be completed by a qualified Professional Agrologist and contain the area's + agricultural capability assessment. +
+ + Please refer to + Removal of Soil & Placement of Fill + on the ALC website for more information + +
-
- warning -
This field is required
+ + + +
+ Detailed Building Plan(s) +
+ Building plans must be the most up to date, current version and should include (1) the total floor area of all + levels and intended use; and (2) interior and exterior views +
+
-
+ -
- - Have you submitted a Notice of Work to the Ministry of Energy, Mines and Low Carbon Innovation (EMLI)? - -
If yes, please attach the Notice of Work in the section below.
-
- +
+ Is your proposal for aggregate extraction or placer mining? +
+ + Yes + + No + + +
+
- Yes - - No - - -
-
- warning -
This field is required
+ warning +
This field is required
+
-
-
- Notice of Work - - Please refer to - Removal of Soil & Placement of Fill + + Have you submitted a Notice of Work to the Ministry of Energy, Mines and Low Carbon Innovation (EMLI)? + +
If yes, please attach the Notice of Work in the section below.
+
+ + Yes + + No + + +
+
- on the ALC website for more information - - -
+ warning +
This field is required
+
+
+ +
+ Notice of Work + + Please refer to + Removal of Soil & Placement of Fill + on the ALC website for more information + + +
+
diff --git a/portal-frontend/src/app/features/applications/edit-submission/proposal/pfrs-proposal/pfrs-proposal.component.scss b/portal-frontend/src/app/features/applications/edit-submission/proposal/pfrs-proposal/pfrs-proposal.component.scss index a4d0e0cc50..f6303c5734 100644 --- a/portal-frontend/src/app/features/applications/edit-submission/proposal/pfrs-proposal/pfrs-proposal.component.scss +++ b/portal-frontend/src/app/features/applications/edit-submission/proposal/pfrs-proposal/pfrs-proposal.component.scss @@ -1,4 +1,5 @@ @use '../../../../../../styles/functions' as *; +@use '../../../../../../styles/colors'; section { margin-top: rem(36); @@ -7,3 +8,27 @@ section { .steps-list { margin: rem(16) 0; } + +.mat-mdc-form-field { + width: 100%; +} + +.info-banner { + background-color: rgba(colors.$secondary-color-light, 0.5); + padding: rem(4); + margin-bottom: 0 !important; +} + +.residential-warning { + width: 74%; + background-color: rgba(colors.$secondary-color-light, 0.5); + margin-bottom: rem(20); + margin-left: 6.5%; +} + +.residential-warning-text { + font-weight: 400; + font-size: rem(12); + margin: rem(10) 0 rem(20) rem(5); + line-height: rem(24); +} diff --git a/portal-frontend/src/app/features/applications/edit-submission/proposal/pfrs-proposal/pfrs-proposal.component.ts b/portal-frontend/src/app/features/applications/edit-submission/proposal/pfrs-proposal/pfrs-proposal.component.ts index 90860ec51c..074b8f06e0 100644 --- a/portal-frontend/src/app/features/applications/edit-submission/proposal/pfrs-proposal/pfrs-proposal.component.ts +++ b/portal-frontend/src/app/features/applications/edit-submission/proposal/pfrs-proposal/pfrs-proposal.component.ts @@ -1,7 +1,6 @@ import { Component, HostListener, OnDestroy, OnInit } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; -import { Router } from '@angular/router'; import { takeUntil } from 'rxjs'; import { ApplicationDocumentDto } from '../../../../../services/application-document/application-document.dto'; import { ApplicationDocumentService } from '../../../../../services/application-document/application-document.service'; @@ -16,6 +15,16 @@ import { parseStringToBoolean } from '../../../../../shared/utils/string-helper' import { EditApplicationSteps } from '../../edit-submission.component'; import { FilesStepComponent } from '../../files-step.partial'; import { SoilTableData } from '../../../../../shared/soil-table/soil-table.component'; +import { MatTableDataSource } from '@angular/material/table'; +import { ConfirmationDialogService } from '../../../../../shared/confirmation-dialog/confirmation-dialog.service'; +import { v4 } from 'uuid'; +import { + STRUCTURE_TYPES, + STRUCTURE_TYPE_OPTIONS, + FormProposedStructure, +} from '../../../../notice-of-intents/edit-submission/additional-information/additional-information.component'; +import { ProposedStructure } from '../../../../../services/notice-of-intent-submission/notice-of-intent-submission.dto'; +import { AddStructureDialogComponent } from '../../../../notice-of-intents/edit-submission/additional-information/add-structure-dialog/add-structure-dialog.component'; @Component({ selector: 'app-pfrs-proposal', @@ -32,17 +41,26 @@ export class PfrsProposalComponent extends FilesStepComponent implements OnInit, DOCUMENT = DOCUMENT_TYPE; + structureTypes = STRUCTURE_TYPES; + structureTypeOptions = STRUCTURE_TYPE_OPTIONS; + structureTypeCounts: Record = Object.fromEntries( + Object.entries(STRUCTURE_TYPES).map(([_, type]) => [type, 0]), + ) as { [key in STRUCTURE_TYPES]: number }; + proposalMap: ApplicationDocumentDto[] = []; crossSections: ApplicationDocumentDto[] = []; reclamationPlan: ApplicationDocumentDto[] = []; + buildingPlans: ApplicationDocumentDto[] = []; noticeOfWork: ApplicationDocumentDto[] = []; areComponentsDirty = false; showProposalMapVirus = false; showCrossSectionVirus = false; showReclamationPlanVirus = false; + showBuildingPlanVirus = false; showNoticeOfWorkVirus = false; + isNewStructure = new FormControl(null, [Validators.required]); isFollowUp = new FormControl(null, [Validators.required]); followUpIDs = new FormControl({ value: null, disabled: true }, [Validators.required]); purpose = new FormControl(null, [Validators.required]); @@ -55,7 +73,15 @@ export class PfrsProposalComponent extends FilesStepComponent implements OnInit, isExtractionOrMining = new FormControl(null, [Validators.required]); hasSubmittedNotice = new FormControl({ value: null, disabled: true }, [Validators.required]); + // Conditional structure questions + soilStructureFarmUseReason = new FormControl(null); + soilStructureResidentialUseReason = new FormControl(null); + soilAgriParcelActivity = new FormControl(null); + soilStructureResidentialAccessoryUseReason = new FormControl(null); + soilStructureOtherUseReason = new FormControl(null); + form = new FormGroup({ + isNewStructure: this.isNewStructure, isFollowUp: this.isFollowUp, followUpIDs: this.followUpIDs, purpose: this.purpose, @@ -67,8 +93,18 @@ export class PfrsProposalComponent extends FilesStepComponent implements OnInit, alternativeMeasures: this.alternativeMeasures, isExtractionOrMining: this.isExtractionOrMining, hasSubmittedNotice: this.hasSubmittedNotice, + soilStructureFarmUseReason: this.soilStructureFarmUseReason, + soilStructureResidentialUseReason: this.soilStructureResidentialUseReason, + soilAgriParcelActivity: this.soilAgriParcelActivity, + soilStructureResidentialAccessoryUseReason: this.soilStructureResidentialAccessoryUseReason, + soilStructureOtherUseReason: this.soilStructureOtherUseReason, }); + structuresForm = new FormGroup({} as any); + proposedStructures: FormProposedStructure[] = []; + structuresSource = new MatTableDataSource(this.proposedStructures); + displayedColumns = ['index', 'type', 'area', 'action']; + private submissionUuid = ''; isMobile = false; removalTableData: SoilTableData = {}; @@ -81,7 +117,8 @@ export class PfrsProposalComponent extends FilesStepComponent implements OnInit, private applicationService: ApplicationSubmissionService, applicationDocumentService: ApplicationDocumentService, dialog: MatDialog, - toastService: ToastService + toastService: ToastService, + private confirmationDialogService: ConfirmationDialogService, ) { super(applicationDocumentService, dialog, toastService); } @@ -135,6 +172,7 @@ export class PfrsProposalComponent extends FilesStepComponent implements OnInit, } this.form.patchValue({ + isNewStructure: applicationSubmission.soilIsNewStructure, isFollowUp: formatBooleanToString(applicationSubmission.soilIsFollowUp), followUpIDs: applicationSubmission.soilFollowUpIDs, purpose: applicationSubmission.purpose, @@ -146,7 +184,21 @@ export class PfrsProposalComponent extends FilesStepComponent implements OnInit, fillProjectDuration: applicationSubmission.fillProjectDuration, isExtractionOrMining: formatBooleanToString(applicationSubmission.soilIsExtractionOrMining), hasSubmittedNotice: formatBooleanToString(applicationSubmission.soilHasSubmittedNotice), + soilStructureFarmUseReason: applicationSubmission.soilStructureFarmUseReason, + soilStructureResidentialUseReason: applicationSubmission.soilStructureResidentialUseReason, + soilAgriParcelActivity: applicationSubmission.soilAgriParcelActivity, + soilStructureResidentialAccessoryUseReason: applicationSubmission.soilStructureResidentialAccessoryUseReason, + soilStructureOtherUseReason: applicationSubmission.soilStructureOtherUseReason, }); + + this.structuresForm = new FormGroup({}); + this.proposedStructures = []; + for (const structure of applicationSubmission.soilProposedStructures) { + console.log(structure); + this.addControl(structure.type, structure.area); + } + this.structuresSource = new MatTableDataSource(this.proposedStructures); + if (this.showErrors) { this.form.markAllAsTouched(); } @@ -157,6 +209,7 @@ export class PfrsProposalComponent extends FilesStepComponent implements OnInit, this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); this.crossSections = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.CROSS_SECTIONS); this.reclamationPlan = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.RECLAMATION_PLAN); + this.buildingPlans = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.BUILDING_PLAN); this.noticeOfWork = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.NOTICE_OF_WORK); }); } @@ -180,6 +233,11 @@ export class PfrsProposalComponent extends FilesStepComponent implements OnInit, this.showReclamationPlanVirus = !res; } + async attachBuildingPlan(file: FileHandle) { + const res = await this.attachFile(file, DOCUMENT_TYPE.BUILDING_PLAN); + this.showBuildingPlanVirus = !res; + } + async attachNoticeOfWork(file: FileHandle) { const res = await this.attachFile(file, DOCUMENT_TYPE.NOTICE_OF_WORK); this.showNoticeOfWorkVirus = !res; @@ -187,6 +245,7 @@ export class PfrsProposalComponent extends FilesStepComponent implements OnInit, protected async save() { if (this.fileId && (this.form.dirty || this.areComponentsDirty)) { + const isNewStructure = this.isNewStructure.getRawValue(); const isFollowUp = this.isFollowUp.getRawValue(); const followUpIDs = this.followUpIDs.getRawValue(); const purpose = this.purpose.getRawValue(); @@ -195,12 +254,22 @@ export class PfrsProposalComponent extends FilesStepComponent implements OnInit, const soilFillTypeToPlace = this.fillTypeToPlace.getRawValue(); const soilAlternativeMeasures = this.alternativeMeasures.getRawValue(); + const updatedStructures: ProposedStructure[] = this.proposedStructures.map((lot) => { + const lotType = this.structuresForm.controls[`${lot.id}-type`].value; + const lotArea = this.structuresForm.controls[`${lot.id}-area`].value; + return { + type: lotType, + area: lotArea ? parseFloat(lotArea) : null, + }; + }); + const updateDto: ApplicationSubmissionUpdateDto = { purpose, soilTypeRemoved, soilFillTypeToPlace, soilReduceNegativeImpacts, soilAlternativeMeasures, + soilIsNewStructure: isNewStructure, soilIsFollowUp: parseStringToBoolean(isFollowUp), soilFollowUpIDs: followUpIDs, soilToRemoveVolume: this.removalTableData?.volume ?? null, @@ -222,7 +291,13 @@ export class PfrsProposalComponent extends FilesStepComponent implements OnInit, soilProjectDuration: this.soilProjectDuration.value, fillProjectDuration: this.fillProjectDuration.value, soilHasSubmittedNotice: parseStringToBoolean(this.hasSubmittedNotice.getRawValue()), + soilStructureFarmUseReason: this.soilStructureFarmUseReason.value, + soilStructureResidentialUseReason: this.soilStructureResidentialUseReason.value, + soilAgriParcelActivity: this.soilAgriParcelActivity.value, + soilStructureResidentialAccessoryUseReason: this.soilStructureResidentialAccessoryUseReason.value, + soilStructureOtherUseReason: this.soilStructureOtherUseReason.value, soilIsExtractionOrMining: parseStringToBoolean(this.isExtractionOrMining.getRawValue()), + soilProposedStructures: updatedStructures, }; const updatedApp = await this.applicationService.updatePending(this.submissionUuid, updateDto); @@ -230,6 +305,81 @@ export class PfrsProposalComponent extends FilesStepComponent implements OnInit, } } + onChangeIsNewStructure(answeredYes: boolean | null) { + const hasValuesThatWillBeCleared: boolean = !!( + (answeredYes && + (this.crossSections.length > 0 || + this.reclamationPlan.length > 0 || + this.noticeOfWork.length > 0 || + this.reduceNegativeImpacts.value || + this.alternativeMeasures.value || + this.isExtractionOrMining.value || + this.hasSubmittedNotice.value)) || + (!answeredYes && + (this.proposedStructures.length > 0 || + this.soilStructureFarmUseReason.value || + this.soilStructureResidentialUseReason.value || + this.soilAgriParcelActivity.value || + this.soilStructureResidentialAccessoryUseReason.value || + this.soilStructureOtherUseReason.value || + this.buildingPlans.length > 0)) + ); + + if (hasValuesThatWillBeCleared) { + this.confirmationDialogService + .openDialog({ + title: 'Are you removing soil in order to build a structure?', + body: 'Warning: Changing your answer will remove all the saved progress on this step. Do you want to continue?', + confirmAction: 'Confirm', + cancelAction: 'Cancel', + }) + .subscribe((isConfirmed) => { + if (isConfirmed) { + if (answeredYes) { + // Clear docs + for (const crossSection of this.crossSections) { + this.onDeleteFile(crossSection); + } + for (const reclamationPlan_ of this.reclamationPlan) { + this.onDeleteFile(reclamationPlan_); + } + for (const noticeOfWork_ of this.noticeOfWork) { + this.onDeleteFile(noticeOfWork_); + } + + // Clear questions + this.reduceNegativeImpacts.reset(); + this.alternativeMeasures.reset(); + this.isExtractionOrMining.reset(); + this.hasSubmittedNotice.reset(); + } else { + // Clear docs + for (const buildingPlan of this.buildingPlans) { + this.onDeleteFile(buildingPlan); + } + + // Clear structures + this.structuresForm = new FormGroup({}); + this.proposedStructures = []; + this.structuresSource = new MatTableDataSource(this.proposedStructures); + for (const type of Object.keys(this.structureTypeCounts) as Array) { + this.structureTypeCounts[type] = 0; + } + + // Clear conditional questions + this.soilStructureFarmUseReason.reset(); + this.soilStructureResidentialUseReason.reset(); + this.soilAgriParcelActivity.reset(); + this.soilStructureResidentialAccessoryUseReason.reset(); + this.soilStructureOtherUseReason.reset(); + } + } else { + this.isNewStructure.setValue(!answeredYes); + } + }); + } + } + onChangeIsFollowUp(selectedValue: string) { if (selectedValue === 'true') { this.followUpIDs.enable(); @@ -252,6 +402,204 @@ export class PfrsProposalComponent extends FilesStepComponent implements OnInit, this.requiresNoticeOfWork = selectedValue === 'true'; } + onChangeStructureType(id: string, newType: STRUCTURE_TYPES) { + const structure = this.proposedStructures.find((structure) => structure.id === id); + + if (!structure) { + console.error('Failed to find structure'); + return; + } + + if (this.hasInput(structure.type)) { + this.confirmationDialogService + .openDialog({ + title: 'Change Structure Type', + body: 'Changing the structure type will remove inputs relevant to the current structure. Do you want to continue?', + confirmAction: 'Confirm', + cancelAction: 'Cancel', + }) + .subscribe((isConfirmed) => { + if (isConfirmed) { + this.setStructureTypeInput(structure, newType); + } else { + this.structuresForm.get(structure.id + '-type')?.setValue(structure.type); + } + }); + } else { + return this.setStructureTypeInput(structure, newType); + } + } + + onChangeArea(id: string, event: Event) { + const input = event.target as HTMLInputElement; + const structure = this.proposedStructures.find((structure) => structure.id === id); + if (!structure) { + console.error('Failed to find structure'); + return; + } + this.setStructureAreaInput(structure, input.value); + } + + private setStructureAreaInput(structure: FormProposedStructure, value: string) { + structure.area = value; + this.form.markAsDirty(); + } + + private hasInput(type: STRUCTURE_TYPES | null) { + switch (type) { + case STRUCTURE_TYPES.FARM_STRUCTURE: + return !!(this.soilAgriParcelActivity.value || this.soilStructureFarmUseReason.value); + + case STRUCTURE_TYPES.ACCESSORY_STRUCTURE: + return !!( + this.soilStructureResidentialUseReason.value || this.soilStructureResidentialAccessoryUseReason.value + ); + + case STRUCTURE_TYPES.OTHER_STRUCTURE: + return !!this.soilStructureOtherUseReason.value; + + case STRUCTURE_TYPES.PRINCIPAL_RESIDENCE: + case STRUCTURE_TYPES.ADDITIONAL_RESIDENCE: + return !!this.soilStructureResidentialUseReason.value; + + case null: + return false; + + default: + return true; + } + } + + private setStructureTypeInput(structure: FormProposedStructure, newType: STRUCTURE_TYPES) { + if (structure.type !== null && this.structureTypeCounts[structure.type] > 0) { + this.structureTypeCounts[structure.type]--; + } + + this.structureTypeCounts[newType]++; + + structure.type = newType; + + this.form.markAsDirty(); + } + + onStructureAdd() { + if (this.isMobile) { + const dialog = this.dialog.open(AddStructureDialogComponent, { + width: '70%', + data: { + structureData: { + options: this.structureTypeOptions, + }, + }, + }); + dialog + .beforeClosed() + .subscribe(async (result: { isEditing: boolean; structureId: string; dto: ProposedStructure }) => { + if (!result) return; + this.addControl(result.dto.type, result.dto.area); + this.structuresSource = new MatTableDataSource(this.proposedStructures); + + this.structureTypeCounts[result.dto.type!]++; + }); + } else { + this.addControl(); + this.structuresSource = new MatTableDataSource(this.proposedStructures); + } + } + + addControl(type: STRUCTURE_TYPES | null = null, area: number | null = null) { + const areaStr = area ? area.toString(10) : null; + const newStructure = { type, area: areaStr, id: v4() }; + this.proposedStructures.push(newStructure); + this.structuresForm.addControl( + `${newStructure.id}-type`, + new FormControl(type, [Validators.required]), + ); + this.structuresForm.addControl( + `${newStructure.id}-area`, + new FormControl(areaStr, [Validators.required]), + ); + + if (type) { + this.structureTypeCounts[type]++; + } + } + + isWarning(index: number, item: ProposedStructure): boolean { + return item.type === STRUCTURE_TYPES.PRINCIPAL_RESIDENCE || item.type === STRUCTURE_TYPES.ADDITIONAL_RESIDENCE; + } + + onStructureRemove(id: string) { + this.confirmationDialogService + .openDialog({ + title: + 'Warning: Deleting the structure type can remove some content already saved to this page. Do you want to continue?', + body: 'Changing the structure type will remove inputs relevant to the current structure. Do you want to continue?', + confirmAction: 'Confirm', + cancelAction: 'Cancel', + }) + .subscribe(async (result) => { + if (result) { + this.deleteStructure(id); + } + }); + } + + private deleteStructure(id: string) { + const structureToDelete = this.proposedStructures.find((structure) => structure.id === id); + + if (!structureToDelete) { + console.error('Failed to find deleted structure'); + return; + } + + this.proposedStructures = this.proposedStructures.filter((structure) => structure.id !== structureToDelete.id); + this.structuresSource = new MatTableDataSource(this.proposedStructures); + this.structuresForm.removeControl(`${id}-type`); + this.structuresForm.removeControl(`${id}-area`); + this.structuresForm.markAsDirty(); + + if (structureToDelete.type !== null && this.structureTypeCounts[structureToDelete.type] > 0) { + this.structureTypeCounts[structureToDelete.type]--; + } + } + + onStructureEdit(id: string) { + const structureToEdit = this.proposedStructures.find((structure) => structure.id === id); + const dialog = this.dialog.open(AddStructureDialogComponent, { + width: '70%', + data: { + isEdit: true, + structureId: structureToEdit?.id, + structureData: { + area: structureToEdit?.area, + type: structureToEdit?.type, + options: this.structureTypeOptions, + }, + }, + }); + dialog + .afterClosed() + .subscribe(async (result: { isEditing: boolean; structureId: string; dto: ProposedStructure }) => { + if (!result) return; + const structureToEdit = this.proposedStructures.find((structure) => structure.id === id); + + if (structureToEdit) { + if (structureToEdit.type !== result.dto.type) { + this.setStructureTypeInput(structureToEdit, result.dto.type!); + } + + structureToEdit.area = result.dto.area ? result.dto.area.toString(10) : null; + structureToEdit.type = result.dto.type; + const areaControl = this.structuresForm.controls[`${structureToEdit?.id}-area`]; + const typeControl = this.structuresForm.controls[`${structureToEdit?.id}-type`]; + areaControl.setValue(structureToEdit.area?.toString()); + typeControl.setValue(structureToEdit.type); + this.structuresForm.markAsDirty(); + } + }); + } + markDirty() { this.areComponentsDirty = true; } diff --git a/portal-frontend/src/app/features/applications/edit-submission/proposal/pofo-proposal/pofo-proposal.component.html b/portal-frontend/src/app/features/applications/edit-submission/proposal/pofo-proposal/pofo-proposal.component.html index 26620cf4e2..a89b6780c1 100644 --- a/portal-frontend/src/app/features/applications/edit-submission/proposal/pofo-proposal/pofo-proposal.component.html +++ b/portal-frontend/src/app/features/applications/edit-submission/proposal/pofo-proposal/pofo-proposal.component.html @@ -25,6 +25,39 @@

Proposal

+
+ Are you placing fill in order to build a structure? +
This can include farm buildings, residences, or accessory buildings.
+
+ + Yes + + No + + +
+ Note: The form will be updated with additional required questions if you are building a structure + +
+
Has the ALC previously received an application or Notice of Intent for this proposal? @@ -40,7 +73,7 @@

Proposal

Yes @@ -48,7 +81,7 @@

Proposal

No @@ -168,65 +201,387 @@

Proposal

Example: Aggregate, topsoil, structural fill, sand, gravel, etc
Characters left: {{ 4000 - fillTypeToPlaceText.textLength }}
-
-