Skip to content

Commit

Permalink
feat(fee-breakdown): Initial setup and logic with useFeeBreakdown()
Browse files Browse the repository at this point in the history
… hook (#4010)
  • Loading branch information
DafyddLlyr authored Dec 5, 2024
1 parent 3c0125f commit 8b284ed
Show file tree
Hide file tree
Showing 11 changed files with 640 additions and 119 deletions.
6 changes: 3 additions & 3 deletions editor.planx.uk/src/@planx/components/Pay/Editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ const Component: React.FC<Props> = (props: Props) => {
</InputRow>
</ModalSectionContent>
</ModalSection>
<GovPayMetadataSection />
<InviteToPaySection />
<FeeBreakdownSection />
<GovPayMetadataSection/>
<InviteToPaySection/>
<FeeBreakdownSection/>
<MoreInformation
changeField={handleChange}
definitionImg={values.definitionImg}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
getDefaultContent,
Pay,
} from "../model";
import { FeeBreakdown } from "./FeeBreakdown";
import { FeeBreakdown } from "./FeeBreakdown/FeeBreakdown";
import InviteToPayForm, { InviteToPayFormProps } from "./InviteToPayForm";
import { PAY_API_ERROR_UNSUPPORTED_TEAM } from "./Pay";

Expand Down
111 changes: 0 additions & 111 deletions editor.planx.uk/src/@planx/components/Pay/Public/FeeBreakdown.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import Box from "@mui/material/Box";
import { styled } from "@mui/material/styles";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell, { tableCellClasses } from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Typography from "@mui/material/Typography";
import React from "react";
import { FONT_WEIGHT_SEMI_BOLD } from "theme";

import { formattedPriceWithCurrencySymbol } from "../../model";
import { useFeeBreakdown } from "./useFeeBreakdown";

const StyledTable = styled(Table)(() => ({
[`& .${tableCellClasses.root}`]: {
paddingLeft: 0,
paddingRight: 0,
},
}));

const BoldTableRow = styled(TableRow)(() => ({
[`& .${tableCellClasses.root}`]: {
fontWeight: FONT_WEIGHT_SEMI_BOLD,
},
}));

const VAT_RATE = 0.2;

const DESCRIPTION =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.";

const Header = () => (
<TableHead>
<BoldTableRow>
<TableCell>Description</TableCell>
<TableCell align="right">Amount</TableCell>
</BoldTableRow>
</TableHead>
);

const ApplicationFee: React.FC<{ amount: number }> = ({ amount }) => (
<TableRow>
<TableCell>Application fee</TableCell>
<TableCell align="right">
{formattedPriceWithCurrencySymbol(amount)}
</TableCell>
</TableRow>
);

const Reductions: React.FC<{ amount?: number, reductions: string[] }> = ({ amount, reductions }) => {
if (!amount) return null;

return (
<>
<TableRow>
<TableCell>Reductions</TableCell>
<TableCell align="right">
{formattedPriceWithCurrencySymbol(-amount)}
</TableCell>
</TableRow>
{
reductions.map((reduction) => (
<TableRow>
<TableCell colSpan={2}>
<Box sx={{ pl: 2, color: "grey" }}>{reduction}</Box>
</TableCell>
</TableRow>
))
}
</>
);
};

// TODO: This won't show as if a fee is 0, we hide the whole Pay component from the user
const Exemptions: React.FC<{ amount: number, exemptions: string[] }> = ({ amount, exemptions }) => {
if (!exemptions.length) return null;

return (
<>
<TableRow>
<TableCell>Exemptions</TableCell>
<TableCell align="right">
{formattedPriceWithCurrencySymbol(-amount)}
</TableCell>
</TableRow>
{
exemptions.map((exemption) => (
<TableRow>
<TableCell colSpan={2}>
<Box sx={{ pl: 2, color: "grey" }}>{exemption}</Box>
</TableCell>
</TableRow>
))
}
</>
);
};

const VAT: React.FC<{ amount?: number }> = ({ amount }) => {
if (!amount) return null;

return (
<TableRow>
<TableCell variant="footer">{`Includes VAT (${
VAT_RATE * 100
}%)`}</TableCell>
<TableCell variant="footer" align="right">
{formattedPriceWithCurrencySymbol(amount)}
</TableCell>
</TableRow>
);
};

const Total: React.FC<{ amount: number }> = ({ amount }) => (
<BoldTableRow>
<TableCell>Total</TableCell>
<TableCell align="right">
{formattedPriceWithCurrencySymbol(amount)}
</TableCell>
</BoldTableRow>
);

export const FeeBreakdown: React.FC = () => {
const breakdown = useFeeBreakdown();
if (!breakdown) return null;

const { amount, reductions, exemptions } = breakdown;

return (
<Box mt={3}>
<Typography variant="h3" mb={1}>
Fee breakdown
</Typography>
<Typography variant="body1" mb={2}>
{DESCRIPTION}
</Typography>
<TableContainer>
<StyledTable data-testid="fee-breakdown-table">
<Header />
<TableBody>
<ApplicationFee amount={amount.applicationFee} />
<Reductions amount={amount.reduction} reductions={reductions}/>
<Exemptions amount={amount.total} exemptions={exemptions}/>
<Total amount={amount.total} />
<VAT amount={amount.vat} />
</TableBody>
</StyledTable>
</TableContainer>
</Box>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export interface FeeBreakdown {
amount: {
applicationFee: number;
total: number;
reduction: number;
vat: number | undefined;
};
reductions: string[];
exemptions: string[];
}

export interface PassportFeeFields {
"application.fee.calculated": number;
"application.fee.payable": number;
"application.fee.payable.vat": number;
"application.fee.reduction.alternative": boolean;
"application.fee.reduction.parishCouncil": boolean;
"application.fee.reduction.sports": boolean;
"application.fee.exemption.disability": boolean;
"application.fee.exemption.resubmission": boolean;
};
Loading

0 comments on commit 8b284ed

Please sign in to comment.