client/components/mma/delivery/records/DeliveryRecordCard.tsx (290 lines of code) (raw):
import { css } from '@emotion/react';
import { from, palette, space, textSans17 } from '@guardian/source/foundations';
import { Checkbox, CheckboxGroup } from '@guardian/source/react-components';
import type { FormEvent } from 'react';
import { dateIsAfter, parseDate } from '@/shared/dates';
import type { DeliveryRecordApiItem } from '@/shared/productResponse';
import { DeliveryRecordInstructions } from './DeliveryRecordInstructions';
import { PageStatus } from './DeliveryRecords';
import { RecordAddress } from './DeliveryRecordsAddress';
import type { DeliveryProblemMap } from './deliveryRecordsApi';
import { RecordStatus } from './DeliveryRecordStatus';
interface DeliveryRecordCardProps {
deliveryRecord: DeliveryRecordApiItem;
listIndex: number;
pageStatus: PageStatus;
deliveryProblemMap: DeliveryProblemMap;
productName?: string;
recordCurrency?: string;
isChecked?: boolean;
showDeliveryInstructions?: boolean;
addRecordToDeliveryProblem?: (id: string) => void;
removeRecordFromDeliveryProblem?: (id: string) => void;
}
export const DeliveryRecordCard = (props: DeliveryRecordCardProps) => {
const dtCss = (ignoreMinWidthAtNonMobile?: boolean) => `
${textSans17};
font-weight: bold;
display: inline-block;
vertical-align: top;
min-width: 10ch;
${from.tablet} {
margin-right: 16px;
${ignoreMinWidthAtNonMobile ? 'min-width: 9ch;' : 'min-width: 12ch;'}
}
`;
const ddCss = `
${textSans17};
display: inline-block;
vertical-align: top;
margin-left: 0;
`;
const recordRowCss = `
margin-bottom: 10px;
`;
return (
<dl
css={css`
border: 1px solid ${palette.neutral['86']};
margin: 0;
padding: ${space[3]}px;
${props.pageStatus === PageStatus.ReportIssueStep2 &&
`padding-left: ${space[3] * 2 + 40}px;`}
width: 100%;
${props.listIndex > 0 && 'border-top: none;'}
position: relative;
opacity: ${props.pageStatus === PageStatus.ReportIssueStep1
? '0.5'
: '1'};
${from.tablet} {
padding: ${space[5]}px;
${props.pageStatus === PageStatus.ReportIssueStep2 &&
`padding-left: ${space[5] * 2 + 40}px;`}
}
`}
>
{props.pageStatus === PageStatus.ReportIssueStep2 && (
<div
css={css`
position: absolute;
top: 0;
left: 0;
height: 100%;
padding: 0 ${space[3]}px;
border-right: 1px solid ${palette.neutral['86']};
${from.tablet} {
padding: 0 18px;
}
`}
>
<CheckboxGroup
name={props.deliveryRecord.id}
cssOverrides={css`
position: relative;
top: 50%;
transform: translateY(-50%);
`}
>
<Checkbox
value={props.deliveryRecord.id}
checked={props.isChecked}
label=""
cssOverrides={css`
margin-right: 0;
`}
onChange={(event: FormEvent<HTMLInputElement>) => {
const inputEl =
event.target as HTMLInputElement;
if (inputEl.checked) {
props.addRecordToDeliveryProblem?.(
props.deliveryRecord.id,
);
} else {
props.removeRecordFromDeliveryProblem?.(
props.deliveryRecord.id,
);
}
}}
/>
</CheckboxGroup>
</div>
)}
<div
css={css`
${recordRowCss}
${from.tablet} {
display: inline-block;
width: 50%;
}
`}
>
<dt
css={css`
${dtCss()}
`}
>
Issue date:
</dt>
<dd
css={css`
${ddCss}
`}
>
{parseDate(props.deliveryRecord.deliveryDate).dateStr()}
</dd>
</div>
<div
css={css`
${recordRowCss}
${from.tablet} {
display: inline-block;
width: 50%;
}
`}
>
<dt
css={css`
${dtCss(true)}
`}
>
Address:
</dt>
<dd
css={css`
${ddCss}
`}
data-qm-masking="blocklist"
>
{props.deliveryRecord.addressLine1 &&
!props.deliveryRecord.hasHolidayStop ? (
<RecordAddress
addressLine1={props.deliveryRecord.addressLine1}
addressLine2={props.deliveryRecord.addressLine2}
town={props.deliveryRecord.addressTown}
postcode={props.deliveryRecord.addressPostcode}
country={props.deliveryRecord.addressCountry}
/>
) : (
'-'
)}
</dd>
</div>
<div
css={css`
${recordRowCss}
`}
>
<dt
css={css`
${dtCss()}
`}
>
Status:
</dt>
<dd
css={css`
${ddCss}
width: calc(100% - 11ch);
${from.tablet} {
width: calc(100% - (13ch + 16px));
}
`}
>
<RecordStatus
isDispatched={!!props.deliveryRecord.addressLine1}
isHolidayStop={!!props.deliveryRecord.hasHolidayStop}
bulkSuspensionReason={
props.deliveryRecord.bulkSuspensionReason
}
productName={props.productName}
isChangedAddress={
!!props.deliveryRecord.isChangedAddress
}
isChangedDeliveryInstruction={
!!props.deliveryRecord.isChangedDeliveryInstruction
}
isFutureRecord={dateIsAfter(
parseDate(props.deliveryRecord.deliveryDate).date,
new Date(new Date().setHours(23, 59, 59, 999)),
)}
deliveryProblem={
(props.deliveryRecord.problemCaseId &&
props.deliveryProblemMap[
props.deliveryRecord.problemCaseId
]?.problemType) ||
null
}
/>
</dd>
</div>
{props.deliveryRecord.problemCaseId && props.deliveryRecord.credit && (
<>
<div
css={css`
${recordRowCss}
margin-top: 10px;
`}
>
<dt
css={css`
${dtCss()}
`}
>
Credit:
</dt>
<dd
css={css`
${ddCss}
width: calc(100% - 11ch);
${from.tablet} {
width: calc(100% - (13ch + 16px));
}
`}
>
{`${props.recordCurrency}${Math.abs(
props.deliveryRecord.credit.amount,
).toFixed(2)} `}
{props.deliveryRecord.credit.invoiceDate && (
<p
css={css`
color: ${palette.neutral['60']};
margin: 0;
${from.tablet} {
display: inline-block;
}
`}
>{`off your ${parseDate(
props.deliveryRecord.credit.invoiceDate,
).dateStr()} payment`}</p>
)}
</dd>
</div>
</>
)}
{props.showDeliveryInstructions && (
<div
css={css`
${recordRowCss}
`}
>
<dt
css={css`
${dtCss()}
`}
>
Instructions:
</dt>
<dd
css={css`
${ddCss}
`}
>
{props.deliveryRecord.deliveryInstruction &&
!props.deliveryRecord.hasHolidayStop ? (
<DeliveryRecordInstructions
message={
props.deliveryRecord.deliveryInstruction
}
/>
) : (
'N/A'
)}
</dd>
</div>
)}
</dl>
);
};