export const APPEAL_TYPES = { SIPS: 846040002, DNS: 846040011, HOUSEHOLDER: 846040004, ADVERT: 846040018, EXCLUDE_QUESTIONNAIRE_1: 846040019, EXCLUDE_QUESTIONNAIRE_2: 846040015, EXCLUDE_QUESTIONNAIRE_3: 846040016 }; export const SPECIALIST_PROCESS = { WRITTEN_REPS: 846040000, HEARING: 846040001 }; export const INVOLVEMENT_TYPES = { LPA: 846040012 }; export const REPRESENTATION_OPTIONS = { QUESTIONNAIRE: "Questionnaire", STATEMENT: "Statement", FINAL_COMMENTS: "Final comments", CONSULTATION_RESPONSE: "Consultation Response", LOCAL_IMPACT_REPORT: "Local Impact Report", MARINE_IMPACT_REPORT: "Marine Impact Report" }; const isValidDate = (date) => date instanceof Date && !Number.isNaN(date.getTime()); const toDateOrNull = (value) => { const date = new Date(value); return isValidDate(date) ? date : null; }; const endOfDay = (date) => { if (!isValidDate(date)) return null; const next = new Date(date); next.setHours(23, 59, 59, 999); return next; }; const isWithinWindow = (now, start, end) => { if (!isValidDate(now) || !isValidDate(start) || !isValidDate(end)) { return false; } return now >= start && now <= end; }; const normalizeCapacity = (value) => (value || "") .toString() .toLowerCase() .replace(/(\band|[\s\-\+\(\)\,\&])/g, ""); export const buildRepresentationContext = ({ detailsObj = {}, appealType, specialistProcess, involvementType, selectedCapacity, isCaseOwner, isNRW, now = new Date() }) => { const isDNS = appealType === APPEAL_TYPES.DNS; const startDate = toDateOrNull( isDNS ? detailsObj.pinswg_applicationacceptedasvalid : detailsObj.pinswg_startdate || detailsObj.pinswg_startdates ); const statementDueDate = endOfDay( toDateOrNull( isDNS ? detailsObj.pinswg_endofrepresentationperiod : detailsObj.pinswg_statementduedate || detailsObj.pinswg_statementsduedate ) ); const finalCommentsDueDate = endOfDay( toDateOrNull( isDNS ? detailsObj.pinswg_endofrepresentationperiod : detailsObj.pinswg_finalcommentsduedate ) ); const capacity = normalizeCapacity(selectedCapacity); const isLPA = involvementType === INVOLVEMENT_TYPES.LPA; return { appealType, specialistProcess, isDNS, isSIPS: appealType === APPEAL_TYPES.SIPS, isLPA, isNRW: !!isNRW, isCaseOwner: !!isCaseOwner, isSelectedAppellant: capacity === "appellant", isSelectedAgent: capacity === "agent", isSelectedInterestedParty: capacity === "interestedparty", now, startDate, statementDueDate, finalCommentsDueDate }; }; export const addQuestionnaire = (options, ctx) => { const excludedTypes = [ APPEAL_TYPES.EXCLUDE_QUESTIONNAIRE_1, APPEAL_TYPES.DNS, APPEAL_TYPES.EXCLUDE_QUESTIONNAIRE_2, APPEAL_TYPES.EXCLUDE_QUESTIONNAIRE_3 ]; const canAdd = ctx.isLPA && !excludedTypes.includes(ctx.appealType) && isWithinWindow(ctx.now, ctx.startDate, ctx.finalCommentsDueDate); if (canAdd) { options.add(REPRESENTATION_OPTIONS.QUESTIONNAIRE); } }; export const addStatements = (options, ctx) => { const isLpaAdvertPart3NoStatement = ctx.isLPA && ctx.appealType === APPEAL_TYPES.ADVERT && ctx.specialistProcess === SPECIALIST_PROCESS.WRITTEN_REPS; const canAddDnsLpaDocs = ctx.isLPA && ctx.isDNS && ctx.appealType !== APPEAL_TYPES.EXCLUDE_QUESTIONNAIRE_1 && !ctx.isCaseOwner && isWithinWindow(ctx.now, ctx.startDate, ctx.finalCommentsDueDate); if (canAddDnsLpaDocs) { options.add(REPRESENTATION_OPTIONS.LOCAL_IMPACT_REPORT); options.add(REPRESENTATION_OPTIONS.STATEMENT); } const canAddStatementForNonDns = !ctx.isDNS && ctx.appealType !== APPEAL_TYPES.HOUSEHOLDER && !isLpaAdvertPart3NoStatement && !ctx.isCaseOwner && isWithinWindow(ctx.now, ctx.startDate, ctx.statementDueDate); if (canAddStatementForNonDns) { options.add(REPRESENTATION_OPTIONS.STATEMENT); } const canAddStatementForDnsNonLpa = ctx.isDNS && !ctx.isLPA && !ctx.isCaseOwner && isWithinWindow(ctx.now, ctx.startDate, ctx.statementDueDate); if (canAddStatementForDnsNonLpa) { options.add(REPRESENTATION_OPTIONS.STATEMENT); } }; export const addFinalComments = (options, ctx) => { const canSubmitFinalCommentsDefault = ctx.isSelectedAppellant || ctx.isSelectedAgent || ctx.isSelectedInterestedParty || ctx.isLPA; const canSubmitFinalComments = ctx.isDNS ? ctx.isLPA : canSubmitFinalCommentsDefault; const isSpecialistNonHearing = ctx.specialistProcess !== SPECIALIST_PROCESS.HEARING; const finalCommentsWindowStart = ctx.isDNS ? ctx.startDate : ctx.statementDueDate; const canAdd = canSubmitFinalComments && isWithinWindow( ctx.now, finalCommentsWindowStart, ctx.finalCommentsDueDate ) && (ctx.appealType !== APPEAL_TYPES.HOUSEHOLDER || isSpecialistNonHearing); if (canAdd) { options.add(REPRESENTATION_OPTIONS.FINAL_COMMENTS); } }; export const addConsultation = (options, ctx) => { if (!ctx.isSIPS) return; options.add(REPRESENTATION_OPTIONS.CONSULTATION_RESPONSE); if (!ctx.isSelectedAppellant) { options.add(REPRESENTATION_OPTIONS.LOCAL_IMPACT_REPORT); } if (ctx.isNRW) { options.add(REPRESENTATION_OPTIONS.MARINE_IMPACT_REPORT); } }; export const buildRepsArrFromContext = (ctx) => { const options = new Set(); addQuestionnaire(options, ctx); addStatements(options, ctx); addFinalComments(options, ctx); addConsultation(options, ctx); return [...options]; };