Skip to content

Commit

Permalink
feat: add decision details information box to application page
Browse files Browse the repository at this point in the history
  • Loading branch information
EmiliaMakelaVincit committed Mar 21, 2024
1 parent f6c786c commit aaf7794
Show file tree
Hide file tree
Showing 15 changed files with 436 additions and 70 deletions.
14 changes: 14 additions & 0 deletions backend/benefit/applications/api/v1/serializers/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,12 @@ class Meta:
"duration_in_months_rounded",
"total_deminimis_amount",
"ahjo_status",
"ahjo_case_id",
"changes",
"archived_for_applicant",
"alterations",
"calculated_benefit_amount",
"ahjo_decision_date",
]
read_only_fields = [
"submitted_at",
Expand All @@ -225,6 +228,9 @@ class Meta:
"total_deminimis_amount",
"changes",
"archived_for_applicant",
"alterations",
"calculated_benefit_amount",
"ahjo_decision_date",
]
extra_kwargs = {
"company_name": {
Expand Down Expand Up @@ -375,6 +381,8 @@ class Meta:

ahjo_status = serializers.SerializerMethodField("get_latest_ahjo_status")

ahjo_decision_date = serializers.SerializerMethodField("get_ahjo_decision_date")

submitted_at = serializers.SerializerMethodField("get_submitted_at")

modified_at = serializers.SerializerMethodField(
Expand Down Expand Up @@ -567,6 +575,12 @@ def get_former_benefit_info(self, obj):
"last_possible_end_date": last_possible_end_date,
}

def get_ahjo_decision_date(self, obj):
if obj.batch is None:
return None

return obj.batch.decision_date

def get_submitted_at(self, obj):
return getattr(obj, "submitted_at", None)

Expand Down
2 changes: 2 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ node_modules
screenshots
report
coverage

certificates
24 changes: 24 additions & 0 deletions frontend/benefit/applicant/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,30 @@
},
"errors": {
"dirtyOrInvalidForm": "Please fill any missing or invalid form fields"
},
"decision": {
"description": {
"accepted": "Helsinki benefit has been granted from {{dateRangeStart}} to {{dateRangeEnd}}",
"rejected": "No Helsinki benefit was granted"
},
"headings": {
"mainHeading": "Decision details",
"caseId": "Case identifier",
"status": "Decision",
"decisionDate": "Date of decision",
"benefitPeriod": "Benefit period",
"benefitAmount": "Total amount of benefit",
"existingAlterations": "Alterations in employment"
},
"alterationList": {
"count_one": "{{count}} alteration in employment reported",
"count_other": "{{count}} alterations in employment reported",
"empty": "No reported alterations in employment. The employment has proceeded as expected."
},
"actions": {
"showDecision": "View the decision",
"reportAlteration": "Report an alteration"
}
}
},
"serviceName": "Helsinki benefit service",
Expand Down
24 changes: 24 additions & 0 deletions frontend/benefit/applicant/public/locales/fi/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,30 @@
},
"errors": {
"dirtyOrInvalidForm": "Täytä lomakkeen puuttuvat tai virheelliset kentät"
},
"decision": {
"description": {
"accepted": "Helsinki-lisää on myönnetty aikavälille {{dateRangeStart}} – {{dateRangeEnd}}",
"rejected": "Helsinki-lisää ei myönnetty"
},
"headings": {
"mainHeading": "Päätöksen tiedot",
"caseId": "Diaarinumero",
"status": "Päätös",
"decisionDate": "Päätös tehty",
"benefitPeriod": "Tukiaika",
"benefitAmount": "Myönnetty tuki yhteensä",
"existingAlterations": "Muutokset työsuhteessa"
},
"alterationList": {
"count_one": "{{count}} ilmoitettu muutos työsuhteessa",
"count_other": "{{count}} ilmoitettua muutosta työsuhteessa",
"empty": "Ei ilmoitettuja keskeytyksiä työsuhteessa. Työsuhde on toteutunut suunnitellusti."
},
"actions": {
"showDecision": "Tarkastele päätöstä",
"reportAlteration": "Ilmoita työsuhteen muutoksesta"
}
}
},
"serviceName": "Helsinki-lisän asiointipalvelu",
Expand Down
24 changes: 24 additions & 0 deletions frontend/benefit/applicant/public/locales/sv/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,30 @@
},
"errors": {
"dirtyOrInvalidForm": "Fyll i eventuella saknade eller ogiltiga formulärfält"
},
"decision": {
"description": {
"accepted": "",
"rejected": ""
},
"headings": {
"mainHeading": "",
"caseId": "",
"status": "",
"decisionDate": "",
"benefitPeriod": "",
"benefitAmount": "",
"existingAlterations": ""
},
"alterationList": {
"count_one": "",
"count_other": "",
"empty": ""
},
"actions": {
"showDecision": "",
"reportAlteration": ""
}
}
},
"serviceName": "E-tjänsten för Helsingforstillägg",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { APPLICATION_STATUSES } from 'benefit-shared/constants';
import { respondAbove } from 'shared/styles/mediaQueries';
import styled from 'styled-components';

Expand All @@ -20,12 +21,25 @@ export const $PageHeader = styled.div`

export const $HeaderItem = styled.div``;

export const $HeaderRightColumnItem = styled.div`
margin-top: ${(props) => props.theme.spacing.m};
${respondAbove('md')`
text-align: right;
`};
`;

export const $PageHeading = styled.h1`
font-size: ${(props) => props.theme.fontSize.heading.xl};
font-weight: normal;
margin: 0;
`;

export const $PageHeadingApplicant = styled.div`
margin-top: var(--spacing-m);
margin-bottom: var(--spacing-m);
`;

export const $PageSubHeading = styled.p`
color: ${(props) => props.theme.colors.coatOfArms};
font-size: ${(props) => props.theme.fontSize.heading.s};
Expand Down Expand Up @@ -89,3 +103,34 @@ export const $NoApplicationsContainer = styled.div`
gap: ${(props) => props.theme.spacing.xs};
margin: ${(props) => props.theme.spacingLayout.xl} 0;
`;

export const $StatusIcon = styled.span`
display: inline-block;
svg {
vertical-align: middle;
}
&.status-icon--${APPLICATION_STATUSES.HANDLING} {
svg {
color: ${(props) => props.theme.colors.info};
}
}
&.status-icon--${APPLICATION_STATUSES.ACCEPTED} {
svg {
color: ${(props) => props.theme.colors.success};
}
}
&.status-icon--${APPLICATION_STATUSES.REJECTED},
&.status-icon--${APPLICATION_STATUSES.CANCELLED} {
svg {
color: ${(props) => props.theme.colors.error};
}
}
&.status-icon--${APPLICATION_STATUSES.INFO_REQUIRED} {
color: ${(props) => props.theme.colors.alertDark};
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { $StatusIcon } from 'benefit/applicant/components/applications/Applications.sc';
import { APPLICATION_STATUSES } from 'benefit-shared/constants';
import { IconAlertCircleFill, IconCheckCircle, IconCheckCircleFill, IconCrossCircleFill } from 'hds-react';
import React from 'react';

type Props = {
status: APPLICATION_STATUSES
}

const StatusIcon = ({ status }: Props): JSX.Element => {
let Component;
switch (status) {
case APPLICATION_STATUSES.DRAFT:
Component = <span />;
break;

case APPLICATION_STATUSES.INFO_REQUIRED:
Component = IconAlertCircleFill;
break;

case APPLICATION_STATUSES.RECEIVED:
Component = IconCheckCircle;
break;

case APPLICATION_STATUSES.ACCEPTED:
Component = IconCheckCircleFill;
break;

case APPLICATION_STATUSES.REJECTED:
Component = IconCrossCircleFill;
break;

case APPLICATION_STATUSES.CANCELLED:
Component = IconCrossCircleFill;
break;

case APPLICATION_STATUSES.HANDLING:
Component = IconCheckCircle;
break;

default:
return <span />;
}

return (
<$StatusIcon className={`status-icon status-icon--${status}`}>
<Component />
</$StatusIcon>
);
};

export default StatusIcon;
Original file line number Diff line number Diff line change
Expand Up @@ -87,25 +87,6 @@ export const $StatusDataValue = styled($DataValue)`
align-items: center;
gap: ${(props) => props.theme.spacing.xs3};
.list-item-status--${APPLICATION_STATUSES.HANDLING} & {
svg {
color: ${(props) => props.theme.colors.info};
}
}
.list-item-status--${APPLICATION_STATUSES.ACCEPTED} & {
svg {
color: ${(props) => props.theme.colors.success};
}
}
.list-item-status--${APPLICATION_STATUSES.REJECTED} &,
.list-item-status--${APPLICATION_STATUSES.CANCELLED} & {
svg {
color: ${(props) => props.theme.colors.error};
}
}
.list-item-status--${APPLICATION_STATUSES.INFO_REQUIRED} & {
color: ${(props) => props.theme.colors.alertDark};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import StatusIcon from 'benefit/applicant/components/applications/StatusIcon';
import { useTranslation } from 'benefit/applicant/i18n';
import { Loading } from 'benefit/applicant/types/common';
import { APPLICATION_STATUSES } from 'benefit-shared/constants';
Expand Down Expand Up @@ -55,7 +56,6 @@ const ListItem: React.FC<ListItemProps> = (props) => {
submittedAt,
applicationNum,
allowedAction,
statusIcon: StatusIcon,
status,
unreadMessagesCount,
validUntil,
Expand Down Expand Up @@ -98,7 +98,7 @@ const ListItem: React.FC<ListItemProps> = (props) => {
<$StatusDataColumn className={`list-item-status--${status}`}>
<$DataHeader>{t(`${translationBase}.common.status`)}</$DataHeader>
<$StatusDataValue>
<StatusIcon />
<StatusIcon status={status}/>
<span>{statusText}</span>
</$StatusDataValue>
</$StatusDataColumn>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ import {
ApplicationListItemData,
} from 'benefit-shared/types/application';
import {
IconAlertCircleFill,
IconCheckCircle,
IconCheckCircleFill,
IconCrossCircleFill,
IconPen,
} from 'hds-react';
import camelCase from 'lodash/camelCase';
Expand Down Expand Up @@ -113,33 +109,6 @@ const useApplicationList = ({
): string =>
t(`${translationStatusBase}.${camelCase(applicationStatus)}`, values);

const getStatusIcon = (applicationStatus: APPLICATION_STATUSES): React.FC => {
switch (applicationStatus) {
case APPLICATION_STATUSES.DRAFT:
return () => React.createElement('span');

case APPLICATION_STATUSES.INFO_REQUIRED:
return IconAlertCircleFill;

case APPLICATION_STATUSES.RECEIVED:
return IconCheckCircle;

case APPLICATION_STATUSES.ACCEPTED:
return IconCheckCircleFill;

case APPLICATION_STATUSES.REJECTED:
return IconCrossCircleFill;

case APPLICATION_STATUSES.CANCELLED:
return IconCrossCircleFill;

case APPLICATION_STATUSES.HANDLING:
return IconCheckCircle;

default:
return () => React.createElement('span');
}
};
const getAllowedActions = (
id: string,
applicationStatus: APPLICATION_STATUSES
Expand Down Expand Up @@ -225,7 +194,6 @@ const useApplicationList = ({
status: appStatus,
unreadMessagesCount: unread_messages_count ?? 0,
batch,
statusIcon: getStatusIcon(appStatus),
contactPersonName,
};
const draftProps = { modifiedAt: modifiedAtWithTime };
Expand Down
Loading

0 comments on commit aaf7794

Please sign in to comment.