Repository: dhsc-govuk/FingertipsNext
Pull request #596: Feature/dhscft 768 export line chart csv
Author: login: stuc-bjss
Created: 2025-05-23T09:12:19Z | Merged: 2025-05-23T12:24:01Z

# Description

Jira ticket: [DHSCFT-767](https://bjss-enterprise.atlassian.net/browse/DHSCFT-767)

Add the csv version of the line chart data



Diff:
diff --git a/frontend/fingertips-frontend/components/molecules/Export/export.types.ts b/frontend/fingertips-frontend/components/molecules/Export/export.types.ts
index 15122480e..448fdc8d4 100644
--- a/frontend/fingertips-frontend/components/molecules/Export/export.types.ts
+++ b/frontend/fingertips-frontend/components/molecules/Export/export.types.ts
@@ -8,3 +8,19 @@ export interface ExportDownload {
   canvas?: HTMLCanvasElement;
   svg?: string;
 }
+
+export enum CsvHeader {
+  IndicatorId = 'Indicator ID',
+  IndicatorName = 'Indicator name',
+  Period = 'Period',
+  Area = 'Area',
+  AreaCode = 'Area code',
+  Benchmark = 'Benchmark',
+  BenchmarkComparison = 'Compared to benchmark',
+  RecentTrend = 'Recent trend',
+  Count = 'Count',
+  ValueUnit = 'Value unit',
+  Value = 'Value',
+  LowerCI = 'Lower confidence limit X%',
+  UpperCI = 'Upper confidence limit X%',
+}
diff --git a/frontend/fingertips-frontend/components/organisms/LineChartTable/LineChartTable.test.tsx b/frontend/fingertips-frontend/components/organisms/LineChartTable/LineChartTable.test.tsx
index a05769547..44a08200a 100644
--- a/frontend/fingertips-frontend/components/organisms/LineChartTable/LineChartTable.test.tsx
+++ b/frontend/fingertips-frontend/components/organisms/LineChartTable/LineChartTable.test.tsx
@@ -19,6 +19,7 @@ import {
   HealthDataPointTrendEnum,
 } from '@/generated-sources/ft-api-client';
 import { allAgesAge, noDeprivation, personsSex } from '@/lib/mocks';
+import { IndicatorDocument } from '@/lib/search/searchTypes';
 
 describe('Line chart table suite', () => {
   const mockHealthData: HealthDataForArea[] = [
@@ -83,7 +84,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={[mockHealthData[0]]}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
           benchmarkComparisonMethod={
             BenchmarkComparisonMethod.CIOverlappingReferenceValue95
           }
@@ -97,7 +98,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={[mockHealthData[0]]}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
         />
       );
       const lineChart = screen.getByTestId('lineChartTable-component');
@@ -109,7 +110,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={[mockHealthData[0]]}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
           benchmarkComparisonMethod={
             BenchmarkComparisonMethod.CIOverlappingReferenceValue95
           }
@@ -146,7 +147,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={[]}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
           benchmarkComparisonMethod={
             BenchmarkComparisonMethod.CIOverlappingReferenceValue99_8
           }
@@ -166,7 +167,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={[mockHealthData[0]]}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
         />
       );
 
@@ -188,7 +189,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={[mockHealthData[0]]}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
         />
       );
 
@@ -200,7 +201,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={[mockHealthData[0]]}
           englandBenchmarkData={undefined}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
         />
       );
 
@@ -220,7 +221,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={[MOCK_HEALTH_DATA_WITH_TRENDS[0]]}
           englandBenchmarkData={undefined}
-          measurementUnit="per 100,000"
+          indicatorMetadata={{ unitLabel: 'per 100,000' } as IndicatorDocument}
         />
       );
 
@@ -238,7 +239,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={mockHealthData}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
           benchmarkComparisonMethod={
             BenchmarkComparisonMethod.CIOverlappingReferenceValue95
           }
@@ -252,7 +253,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={mockHealthData}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
           benchmarkComparisonMethod={
             BenchmarkComparisonMethod.CIOverlappingReferenceValue95
           }
@@ -291,7 +292,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={mockHealthData}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
         />
       );
       expect(
@@ -307,7 +308,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={mockHealthData}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
         />
       );
 
@@ -319,7 +320,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={MOCK_HEALTH_DATA_WITH_TRENDS}
           englandBenchmarkData={undefined}
-          measurementUnit="per 100,000"
+          indicatorMetadata={{ unitLabel: 'per 100,000' } as IndicatorDocument}
         />
       );
 
@@ -345,7 +346,7 @@ describe('Line chart table suite', () => {
           healthIndicatorData={mockHealthData}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
           groupIndicatorData={MOCK_PARENT_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
         />
       );
 
@@ -363,7 +364,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={mockHealthData}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
         />
       );
       expect(screen.getAllByRole('columnheader')[7]).toHaveTextContent(
@@ -377,7 +378,7 @@ describe('Line chart table suite', () => {
           healthIndicatorData={mockHealthData}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
           groupIndicatorData={MOCK_PARENT_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
         />
       );
       expect(screen.getAllByRole('cell')).toHaveLength(
@@ -390,7 +391,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={[MOCK_ENGLAND_DATA]}
           groupIndicatorData={MOCK_PARENT_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
         />
       );
 
@@ -460,7 +461,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={[mockHealthData[0]]}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
           benchmarkComparisonMethod={BenchmarkComparisonMethod.Quintiles}
         />
       );
@@ -494,7 +495,7 @@ describe('Line chart table suite', () => {
         <LineChartTable
           healthIndicatorData={[mockHealthArea1, mockHealthArea2]}
           englandBenchmarkData={MOCK_ENGLAND_DATA}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
           benchmarkComparisonMethod={
             BenchmarkComparisonMethod.CIOverlappingReferenceValue95
           }
@@ -544,7 +545,7 @@ describe('Line chart table suite', () => {
           healthIndicatorData={MOCK_HEALTH_DATA}
           englandBenchmarkData={mockBenchmarkAreaWithEarlyYear}
           groupIndicatorData={mockGroupAreaWithLateYear}
-          measurementUnit="%"
+          indicatorMetadata={{ unitLabel: '%' } as IndicatorDocument}
           benchmarkComparisonMethod={
             BenchmarkComparisonMethod.CIOverlappingReferenceValue95
           }
diff --git a/frontend/fingertips-frontend/components/organisms/LineChartTable/convertLineChartTableToCsvData.test.ts b/frontend/fingertips-frontend/components/organisms/LineChartTable/convertLineChartTableToCsvData.test.ts
new file mode 100644
index 000000000..9df154505
--- /dev/null
+++ b/frontend/fingertips-frontend/components/organisms/LineChartTable/convertLineChartTableToCsvData.test.ts
@@ -0,0 +1,140 @@
+import { convertLineChartTableToCsvData } from './convertLineChartTableToCsvData';
+import { CsvHeader } from '@/components/molecules/Export/export.types';
+import { HealthDataForArea } from '@/generated-sources/ft-api-client';
+import { IndicatorDocument } from '@/lib/search/searchTypes';
+
+describe('convertLineChartTableToCsvData', () => {
+  const baseHealthData = [
+    {
+      areaCode: 'A1',
+      areaName: 'Area One',
+      healthData: [
+        {
+          year: '2022',
+          benchmarkComparison: {
+            outcome: 'Better',
+            benchmarkAreaCode: 'B1',
+          },
+          count: 100,
+          value: 10.2,
+          lowerCi: 9.5,
+          upperCi: 11.0,
+          trend: 'Increasing',
+        },
+      ],
+    },
+  ] as unknown as HealthDataForArea[];
+
+  const groupAreaData = {
+    areaCode: 'G1',
+    areaName: 'Group Area',
+    healthData: [
+      {
+        year: '2022',
+        benchmarkComparison: {
+          outcome: 'Worse',
+          benchmarkAreaCode: 'B1',
+        },
+        count: 80,
+        value: 12.3,
+        lowerCi: 11.0,
+        upperCi: 13.5,
+        trend: 'Decreasing',
+      },
+    ],
+  } as unknown as HealthDataForArea;
+
+  const benchmarkAreaData = {
+    areaCode: 'B1',
+    areaName: 'Benchmark Area',
+    healthData: [
+      {
+        year: '2022',
+        benchmarkComparison: null,
+        count: 200,
+        value: 11.1,
+        lowerCi: 10.0,
+        upperCi: 12.0,
+        trend: 'Not yet calculated',
+      },
+    ],
+  } as unknown as HealthDataForArea;
+
+  it('should generate correct CSV headers and rows', () => {
+    const result = convertLineChartTableToCsvData(
+      {
+        indicatorID: '1',
+        indicatorName: 'Indicator',
+        unitLabel: '%',
+      } as IndicatorDocument,
+      baseHealthData,
+      groupAreaData,
+      benchmarkAreaData,
+      95
+    );
+
+    expect(result[0]).toEqual([
+      CsvHeader.IndicatorId,
+      CsvHeader.IndicatorName,
+      CsvHeader.Period,
+      CsvHeader.Area,
+      CsvHeader.AreaCode,
+      CsvHeader.Benchmark,
+      CsvHeader.BenchmarkComparison,
+      CsvHeader.RecentTrend,
+      CsvHeader.Count,
+      CsvHeader.ValueUnit,
+      CsvHeader.Value,
+      'Lower confidence limit 95%',
+      'Upper confidence limit 95%',
+    ]);
+
+    expect(result[1]).toEqual([
+      '1',
+      'Indicator',
+      '2022',
+      'Area One',
+      'A1',
+      'B1',
+      'Better',
+      'Increasing',
+      100,
+      '%',
+      10.2,
+      9.5,
+      11.0,
+    ]);
+
+    expect(result[2]).toEqual([
+      '1',
+      'Indicator',
+      '2022',
+      'Group: Group Area',
+      'G1',
+      'B1',
+      'Worse',
+      'Decreasing',
+      80,
+      '%',
+      12.3,
+      11.0,
+      13.5,
+    ]);
+
+    expect(result[3]).toEqual([
+      '1',
+      'Indicator',
+      '2022',
+      'Benchmark Area',
+      'B1',
+      undefined,
+      undefined,
+      'Not yet calculated',
+      200,
+      '%',
+      11.1,
+      10.0,
+      12.0,
+    ]);
+  });
+});
diff --git a/frontend/fingertips-frontend/components/organisms/LineChartTable/convertLineChartTableToCsvData.ts b/frontend/fingertips-frontend/components/organisms/LineChartTable/convertLineChartTableToCsvData.ts
new file mode 100644
index 000000000..60fcccd8e
--- /dev/null
+++ b/frontend/fingertips-frontend/components/organisms/LineChartTable/convertLineChartTableToCsvData.ts
@@ -0,0 +1,71 @@
+import { CsvData, CsvRow } from '@/lib/downloadHelpers/convertToCsv';
+import { HealthDataForArea } from '@/generated-sources/ft-api-client';
+import { CsvHeader } from '@/components/molecules/Export/export.types';
+import { IndicatorDocument } from '@/lib/search/searchTypes';
+
+export const convertLineChartTableToCsvData = (
+  indicatorMetadata: IndicatorDocument,
+  healthIndicatorData: HealthDataForArea[],
+  groupAreaData?: HealthDataForArea,
+  benchmarkAreaData?: HealthDataForArea,
+  confidenceLimit = 0
+): CsvData => {
+  const csvHeaders: CsvRow = [
+    CsvHeader.IndicatorId,
+    CsvHeader.IndicatorName,
+    CsvHeader.Period,
+    CsvHeader.Area,
+    CsvHeader.AreaCode,
+    CsvHeader.Benchmark,
+    CsvHeader.BenchmarkComparison,
+    CsvHeader.RecentTrend,
+    CsvHeader.Count,
+    CsvHeader.ValueUnit,
+    CsvHeader.Value,
+    CsvHeader.LowerCI.replace('X', String(confidenceLimit)),
+    CsvHeader.UpperCI.replace('X', String(confidenceLimit)),
+  ];
+
+  const csvData: CsvData = [csvHeaders];
+  const allAreaData = [
+    ...healthIndicatorData,
+    groupAreaData,
+    benchmarkAreaData,
+  ];
+  allAreaData.forEach((area) => {
+    if (!area) return;
+    const { areaName, areaCode } = area;
+    const benchmarkPrefix =
+      area.areaCode === groupAreaData?.areaCode ? 'Group: ' : '';
+
+    area.healthData.forEach((healthPoint) => {
+      const {
+        year,
+        benchmarkComparison,
+        count,
+        value,
+        lowerCi,
+        upperCi,
+        trend,
+      } = healthPoint;
+      const { outcome, benchmarkAreaCode } = benchmarkComparison ?? {};
+      csvData.push([
+        indicatorMetadata.indicatorID,
+        indicatorMetadata.indicatorName,
+        year,
+        `${benchmarkPrefix}${areaName}`,
+        areaCode,
+        benchmarkAreaCode,
+        outcome,
+        trend,
+        count,
+        indicatorMetadata?.unitLabel,
+        value,
+        lowerCi,
+        upperCi,
+      ]);
+    });
+  });
+
+  return csvData;
+};
diff --git a/frontend/fingertips-frontend/components/organisms/LineChartTable/index.tsx b/frontend/fingertips-frontend/components/organisms/LineChartTable/index.tsx
index a4890453a..6b9975855 100644
--- a/frontend/fingertips-frontend/components/organisms/LineChartTable/index.tsx
+++ b/frontend/fingertips-frontend/components/organisms/LineChartTable/index.tsx
@@ -33,6 +33,8 @@ import {
 } from '@/lib/chartHelpers/chartHelpers';
 import { formatNumber, formatWholeNumber } from '@/lib/numberFormatter';
 import { areaCodeForEngland } from '@/lib/chartHelpers/constants';
+import { convertLineChartTableToCsvData } from '@/components/organisms/LineChartTable/convertLineChartTableToCsvData';
+import { IndicatorDocument } from '@/lib/search/searchTypes';
 import { ExportOptionsButton } from '@/components/molecules/Export/ExportOptionsButton';
 
 export enum LineChartTableHeadingEnum {
@@ -49,7 +51,7 @@ export interface LineChartTableProps {
   healthIndicatorData: HealthDataForArea[];
   englandBenchmarkData?: HealthDataForArea;
   groupIndicatorData?: HealthDataForArea;
-  measurementUnit?: string;
+  indicatorMetadata?: IndicatorDocument;
   benchmarkComparisonMethod?: BenchmarkComparisonMethod;
   polarity?: IndicatorPolarity;
 }
@@ -225,7 +227,7 @@ export function LineChartTable({
   healthIndicatorData,
   englandBenchmarkData,
   groupIndicatorData,
-  measurementUnit,
+  indicatorMetadata,
   benchmarkComparisonMethod = BenchmarkComparisonMethod.Unknown,
   polarity = IndicatorPolarity.Unknown,
 }: Readonly<LineChartTableProps>) {
@@ -293,6 +295,16 @@ export function LineChartTable({
     })
     .toSorted((a, b) => a.year - b.year);
 
+  const csvData = indicatorMetadata
+    ? convertLineChartTableToCsvData(
+        indicatorMetadata,
+        healthIndicatorData,
+        showGroupColumn ? groupIndicatorData : undefined,
+        showBenchmarkColumn ? englandBenchmarkData : undefined,
+        confidenceLimit
+      )
+    : undefined;
+
   return (
     <>
       <StyledDivWithScrolling data-testid="lineChartTable-component">
@@ -378,14 +390,14 @@ export function LineChartTable({
                         key={`header-${heading}`}
                         heading={heading}
                         areaIndex={areaIndex}
-                        units={measurementUnit}
+                        units={indicatorMetadata?.unitLabel}
                       />
                     ))
                 )}
                 {showGroupColumn ? (
                   <StyledLightGreySubHeader>
                     Value
-                    <StyledSpan>{measurementUnit}</StyledSpan>
+                    <StyledSpan>{indicatorMetadata?.unitLabel}</StyledSpan>
                   </StyledLightGreySubHeader>
                 ) : null}
                 {showBenchmarkColumn ? (
@@ -393,7 +405,7 @@ export function LineChartTable({
                     data-testid={`header-benchmark-value`}
                   >
                     {LineChartTableHeadingEnum.BenchmarkValue}{' '}
-                    <StyledSpan>{measurementUnit}</StyledSpan>
+                    <StyledSpan>{indicatorMetadata?.unitLabel}</StyledSpan>
                   </StyledStickyRightHeader>
                 ) : null}
               </Table.Row>
@@ -443,13 +455,7 @@ export function LineChartTable({
           ))}
         </StyledTable>
       </StyledDivWithScrolling>
-      <ExportOptionsButton
-        targetId={'lineChartTable'}
-        csvData={[
-          ['a', 'b', 'c'],
-          [1, 2, 3],
-        ]}
-      />
+      <ExportOptionsButton targetId={'lineChartTable'} csvData={csvData} />
     </>
   );
 }
diff --git a/frontend/fingertips-frontend/components/viewPlots/OneIndicatorOneAreaViewPlots/index.tsx b/frontend/fingertips-frontend/components/viewPlots/OneIndicatorOneAreaViewPlots/index.tsx
index 2d0714ed5..fea879f27 100644
--- a/frontend/fingertips-frontend/components/viewPlots/OneIndicatorOneAreaViewPlots/index.tsx
+++ b/frontend/fingertips-frontend/components/viewPlots/OneIndicatorOneAreaViewPlots/index.tsx
@@ -145,7 +145,7 @@ export function OneIndicatorOneAreaViewPlots({
                     healthIndicatorData={areaDataWithoutInequalities}
                     englandBenchmarkData={englandDataWithoutInequalities}
                     groupIndicatorData={groupDataWithoutInequalities}
-                    measurementUnit={indicatorMetadata?.unitLabel}
+                    indicatorMetadata={indicatorMetadata}
                     benchmarkComparisonMethod={benchmarkComparisonMethod}
                     polarity={polarity}
                   />
diff --git a/frontend/fingertips-frontend/components/viewPlots/OneIndicatorTwoOrMoreAreasViewPlots/index.tsx b/frontend/fingertips-frontend/components/viewPlots/OneIndicatorTwoOrMoreAreasViewPlots/index.tsx
index ffcf84714..a74db8cea 100644
--- a/frontend/fingertips-frontend/components/viewPlots/OneIndicatorTwoOrMoreAreasViewPlots/index.tsx
+++ b/frontend/fingertips-frontend/components/viewPlots/OneIndicatorTwoOrMoreAreasViewPlots/index.tsx
@@ -149,7 +149,7 @@ export function OneIndicatorTwoOrMoreAreasViewPlots({
                     healthIndicatorData={dataWithoutEnglandOrGroup}
                     englandBenchmarkData={englandData}
                     groupIndicatorData={groupData}
-                    measurementUnit={indicatorMetadata?.unitLabel}
+                    indicatorMetadata={indicatorMetadata}
                     benchmarkComparisonMethod={benchmarkMethod}
                     polarity={polarity}
                   />


Reviews:
user: login: gareth-allan
body: Looks good, just a couple of comments on the header values.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T10:20:38Z
user: login: gareth-allan
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T11:17:48Z

Review comments:
diff_hunk: @@ -8,3 +8,19 @@ export interface ExportDownload {
   canvas?: HTMLCanvasElement;
   svg?: string;
 }
+
+export enum CsvHeader {
+  IndicatorId = 'Indicator Id',
+  IndicatorName = 'Indicator Name',
path: frontend/fingertips-frontend/components/molecules/Export/export.types.ts
user: login: gareth-allan
body: ```suggestion
  IndicatorName = 'Indicator name',
```
Just for consistency with the casing of the other columns/the spreadsheet.
created_at: 2025-05-23T10:00:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,3 +8,19 @@ export interface ExportDownload {
   canvas?: HTMLCanvasElement;
   svg?: string;
 }
+
+export enum CsvHeader {
+  IndicatorId = 'Indicator Id',
path: frontend/fingertips-frontend/components/molecules/Export/export.types.ts
user: login: gareth-allan
body: I've styled this as:
```suggestion
  IndicatorId = 'Indicator ID',
```

I think this matches the spreadsheet too.
created_at: 2025-05-23T10:00:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -49,7 +51,7 @@ export interface LineChartTableProps {
   healthIndicatorData: HealthDataForArea[];
   englandBenchmarkData?: HealthDataForArea;
   groupIndicatorData?: HealthDataForArea;
-  measurementUnit?: string;
+  indicatorMetadata?: IndicatorDocument;
path: frontend/fingertips-frontend/components/organisms/LineChartTable/index.tsx
user: login: gareth-allan
body: Ah! I was using the indicator details from the health data API in mine, but this is better!
created_at: 2025-05-23T10:11:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,71 @@
+import { CsvData, CsvRow } from '@/lib/downloadHelpers/convertToCsv';
+import { HealthDataForArea } from '@/generated-sources/ft-api-client';
+import { CsvHeader } from '@/components/molecules/Export/export.types';
+import { IndicatorDocument } from '@/lib/search/searchTypes';
+
+export const convertLineChartTableToCsvData = (
+  indicatorMetadata: IndicatorDocument,
+  healthIndicatorData: HealthDataForArea[],
+  groupAreaData?: HealthDataForArea,
+  benchmarkAreaData?: HealthDataForArea,
+  confidenceLimit = 0
+): CsvData => {
+  const csvHeaders: CsvRow = [
+    CsvHeader.IndicatorId,
+    CsvHeader.IndicatorName,
+    CsvHeader.Period,
+    CsvHeader.Area,
+    CsvHeader.AreaCode,
+    CsvHeader.Benchmark,
+    CsvHeader.BenchmarkComparison,
+    CsvHeader.RecentTrend,
+    CsvHeader.Count,
+    CsvHeader.ValueUnit,
+    CsvHeader.Value,
+    CsvHeader.LowerCI.replace('X', String(confidenceLimit)),
+    CsvHeader.UpperCI.replace('X', String(confidenceLimit)),
+  ];
+
+  const csvData: CsvData = [csvHeaders];
+  const allAreaData = [
+    ...healthIndicatorData,
+    groupAreaData,
+    benchmarkAreaData,
+  ];
path: frontend/fingertips-frontend/components/organisms/LineChartTable/convertLineChartTableToCsvData.ts
user: login: gareth-allan
body: I appreciate the order of area, group, benchmark matches what's in the spreadsheet, but it doesn't match what's in the spreadsheet/been done in #594 for the pop pyramid table. Not necessarily one to block this PR, but probably something we should clarify as it's inconsistent.
created_at: 2025-05-23T10:19:55Z
author_association: CONTRIBUTOR

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-05-23T10:30:53Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=dhsc-govuk_FingertipsNext&pullRequest=596) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [2 New issues](https://sonarcloud.io/project/issues?id=dhsc-govuk_FingertipsNext&pullRequest=596&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=dhsc-govuk_FingertipsNext&pullRequest=596&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=dhsc-govuk_FingertipsNext&pullRequest=596&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=dhsc-govuk_FingertipsNext&pullRequest=596&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=dhsc-govuk_FingertipsNext&pullRequest=596&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=dhsc-govuk_FingertipsNext&pullRequest=596)


author_association: NONE