Files
pedwfrontend/components/admin/tabs/appealsWithStatus.js
T
Robert Bond 18a05d4be8 Merged PR 2357: dashboards in admin for appeals and lpa
dashboards in admin for appeals and lpa

Related work items: #23527
2026-05-29 16:35:27 +00:00

295 lines
14 KiB
JavaScript

// // components/admin/tabs/AccountsTab.js
// import Link from "next/link";
// export default function AppealsWithStatusTab({ statusObj }) {
// return (
// <div>
// <h1>User Accounts</h1>
// <dl className="govuk-summary-list govuk-!-margin-bottom-9 results">
// <div className="govuk-summary-list__row results-headings">
// <dd className="govuk-summary-list__key govuk-!-font-size-16">
// Name
// </dd>
// <dd className="govuk-summary-list__key govuk-!-font-size-16">
// Last accessed
// </dd>
// </div>
// {statusObj.map((appeal) => (
// <div key={appeal.id} className="govuk-summary-list__row">
// <dd className="govuk-summary-list__value govuk-!-font-size-16 ">
// <Link
// target="_blank"
// href={`/auth/signin2?email=${appeal.value}`}
// >
// {appeal.value}
// </Link>
// <br />
// <dl className="govuk-summary-list govuk-!-margin-bottom-9 govuk-!-margin-left-9 results">
// <div className="govuk-summary-list__row results-headings">
// <dd className="govuk-summary-list__key govuk-!-font-size-16">
// Name
// </dd>
// <dd className="govuk-summary-list__key govuk-!-font-size-16">
// Last accessed
// </dd>
// </div>
// {appeal.statuses.map((statuses) => (
// <div
// key={appeal.id}
// className="govuk-summary-list__row"
// >
// <dd className="govuk-summary-list__value govuk-!-font-size-16 ">
// {statuses.value}
// </dd>
// <dd className="govuk-summary-list__value govuk-!-font-size-16 ">
// Total: {statuses.caseCount}
// </dd>
// </div>
// ))}
// </dl>
// </dd>
// <dd className="govuk-summary-list__value govuk-!-font-size-16 ">
// Total: {appeal.caseCount}
// </dd>
// </div>
// ))}
// </dl>
// </div>
// );
// }
import { useState } from "react";
import Link from "next/link";
export default function AppealsWithStatusTab({ statusObj = [] }) {
const [openSections, setOpenSections] = useState({});
const toggleSection = (index) => {
setOpenSections((current) => ({
...current,
[index]: !current[index]
}));
};
const showAll = () => {
const allOpen = {};
statusObj.forEach((_, index) => {
allOpen[index] = true;
});
setOpenSections(allOpen);
};
const hideAll = () => {
setOpenSections({});
};
const allExpanded =
statusObj.length > 0 &&
statusObj.every((_, index) => openSections[index]);
const sortedAppeals = [...statusObj].sort(
(a, b) => (b.caseCount || 0) - (a.caseCount || 0)
);
const maxCount = sortedAppeals[0]?.caseCount || 1;
return (
<div>
<h1 className="govuk-heading-l">Case status by appeal type</h1>
<div className="govuk-!-margin-bottom-6">
<h2 className="govuk-heading-m">Case counts by appeal type</h2>
<dl className="appeal-count-chart">
{sortedAppeals.map((appeal) => {
const maxCount = sortedAppeals[0]?.caseCount || 1;
const width =
((appeal.caseCount || 0) / maxCount) * 100;
return (
<div
className="appeal-count-chart__row"
key={appeal.appealType}
>
<dt className="appeal-count-chart__label">
{appeal.value}
</dt>
<dd className="appeal-count-chart__bar-wrapper">
<span
className="appeal-count-chart__bar"
style={{ width: `${width}%` }}
/>
<span className="appeal-count-chart__count">
{appeal.caseCount || 0}
</span>
</dd>
</div>
);
})}
</dl>
</div>
<div className="govuk-!-margin-bottom-6">
<h2 className="govuk-heading-m">Case stages by appeal type</h2>
<dl className="appeal-stage-chart">
{sortedAppeals.map((appeal) => (
<div
className="appeal-stage-chart__row"
key={appeal.appealType}
>
<dt className="appeal-stage-chart__label">
{appeal.value}
</dt>
<dd className="appeal-stage-chart__bar-wrapper">
<div
className="appeal-stage-chart__bar"
style={{
width: `${((appeal.caseCount || 0) / maxCount) * 100}%`
}}
aria-label={`${appeal.value}, ${appeal.caseCount || 0} cases`}
>
{(appeal.statuses || [])
.filter(
(status) => status.caseCount > 0
)
.sort(
(a, b) => b.caseCount - a.caseCount
)
.map((status, index) => (
<span
key={status.statuscode}
className={`appeal-stage-chart__segment appeal-stage-chart__segment--${index % 6}`}
style={{
width: `${((status.caseCount || 0) / (appeal.caseCount || 1)) * 100}%`
}}
title={`${status.value}: ${status.caseCount}`}
/>
))}
</div>
<span className="appeal-stage-chart__count">
{appeal.caseCount || 0}
</span>
</dd>
</div>
))}
</dl>
</div>
<div className="govuk-accordion__controls">
<button
type="button"
className="govuk-accordion__show-all"
onClick={allExpanded ? hideAll : showAll}
>
<span className="govuk-accordion__show-all-text">
{allExpanded
? "Hide all sections"
: "Show all sections"}
</span>
</button>
</div>
<div className="govuk-accordion" id="appeals-with-status-accordion">
{[...statusObj]
.sort((a, b) => (b.caseCount || 0) - (a.caseCount || 0))
.map((appeal, index) => {
const isOpen = !!openSections[index];
return (
<div
className={
isOpen
? "govuk-accordion__section govuk-accordion__section--expanded"
: "govuk-accordion__section"
}
key={appeal.appealType || index}
>
<div className="govuk-accordion__section-header ">
<h2 className="govuk-accordion__section-heading">
<button
type="button"
className="govuk-accordion__section-button "
id={`appeal-status-heading-${index}`}
aria-expanded={isOpen}
aria-controls={`appeal-status-content-${index}`}
onClick={() => toggleSection(index)}
>
<span
style={{
display: "flex",
justifyContent:
"space-between",
alignItems: "center",
width: "100%",
paddingRight: "20px" // leaves room for accordion icon
}}
>
<span className="govuk-heading-s ">
{appeal.value}
</span>
<span
className="govuk-body-s"
style={{
fontWeight: "normal"
}}
>
{appeal.caseCount || 0}{" "}
cases
</span>
</span>
</button>
</h2>
</div>
<div
id={`appeal-status-content-${index}`}
className="govuk-accordion__section-content"
aria-labelledby={`appeal-status-heading-${index}`}
hidden={!isOpen}
>
<dl className="govuk-summary-list govuk-!-margin-left-9">
{(appeal.statuses || [])
.sort(
(a, b) =>
(b.caseCount || 0) -
(a.caseCount || 0)
)
.map((status) => (
<div
className="govuk-summary-list__row"
key={status.statuscode}
>
<dt className="govuk-summary-list__key">
<Link
target="_blank"
href={`/advancedsearchresults?apt=${appeal.appealType}&statuscode=${status.statuscode}`}
>
{status.value}
</Link>
</dt>
<dd className="govuk-summary-list__value">
{status.caseCount || 0}
</dd>
</div>
))}
</dl>
</div>
</div>
);
})}
</div>
</div>
);
}