Skip to content

Commit

Permalink
Update patron stats and factor out more components.
Browse files Browse the repository at this point in the history
  • Loading branch information
tdilauro committed Aug 14, 2024
1 parent af8d574 commit 8b79974
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 161 deletions.
184 changes: 34 additions & 150 deletions src/components/LibraryStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import {
import StatsCollectionsBarChart from "./StatsCollectionsBarChart";
import StatsCollectionsList from "./StatsCollectionsList";
import StatsGroup from "./StatsGroup";
import StatsTotalCirculationsGroup from "./StatsTotalCirculationsGroup";
import StatsPatronGroup from "./StatsPatronGroup";
import StatsInventoryGroup from "./StatsInventoryGroup";
import StatsCollectionsGroup from "./StatsCollectionsGroup";

export interface LibraryStatsProps {
stats: LibraryStatistics;
Expand Down Expand Up @@ -54,167 +58,47 @@ const LibraryStats = ({ stats, library }: LibraryStatsProps) => {
const dashboardTitle = library
? `${libraryName || libraryKey} Dashboard`
: ALL_LIBRARIES_HEADING;
const libraryOrLibraries = library ? "library's" : "libraries'";
return (
<div className="library-stats">
<h2>{dashboardTitle}</h2>
<ul className="stats">
<li className="stat-group">{renderPatronsGroup(patrons)}</li>
<li className="stat-group">{renderCirculationsGroup(patrons)}</li>
<li className="stat-group">
{renderInventoryGroup(
inventory,
inventoryReportRequestEnabled,
library
)}
<StatsPatronGroup
withActiveLoan={patrons.withActiveLoan}
withActiveLoanOrHold={patrons.withActiveLoanOrHold}
heading="Current Circulation Activity"
description="Real-time patron circulation information of the Palace System."
/>
</li>
<li className="stat-group">
<StatsTotalCirculationsGroup
{...patrons}
heading="Circulation Totals"
/>
</li>
<li className="stat-group">
<StatsInventoryGroup
library={library}
inventory={inventory}
inventoryReportsEnabled={inventoryReportRequestEnabled}
/>
</li>
<li className="stat-group stat-group-wide">
{renderConfiguredCollections(collections, showBarChart)}
<StatsCollectionsGroup
heading={"Configured Collections"}
description={`
The following collections are configured in your ${libraryOrLibraries}
implementation of the Palace system and are available to your users
through the Palace app.
`}
collections={collections}
showBarChart={showBarChart}
/>
</li>
</ul>
</div>
);
};

const renderPatronsGroup = (patrons: PatronStatistics) => {
return (
<StatsGroup
heading="Patrons"
description="Patrons currently registered in Palace"
>
<ul>
<SingleStatListItem
label="Total Patrons"
value={patrons.total}
tooltip="Total number of patrons."
/>
<SingleStatListItem
label="Patrons With Active Loans"
value={patrons.withActiveLoan}
tooltip="Number of patron with at least one active loan."
/>
<SingleStatListItem
label="Patrons With Active Loans or Holds"
value={patrons.withActiveLoanOrHold}
tooltip="Number of patrons with at least one active loan or at least one hold."
/>
</ul>
</StatsGroup>
);
};

const renderCirculationsGroup = (patrons: PatronStatistics) => {
const description =
"The following circulation data displays real-time usage of the Palace system.";
return (
<StatsGroup heading="Circulation" description={description}>
<ul>
<SingleStatListItem
label="Active Loans"
value={patrons.loans}
tooltip="Total number of active loans for all patrons."
/>
<SingleStatListItem
label="Active Holds"
tooltip="Total number of active holds for all patrons."
value={patrons.holds}
/>
</ul>
</StatsGroup>
);
};

const renderInventoryGroup = (
inventory: InventoryStatistics,
inventoryReportsEnabled: boolean,
library?: string
) => {
const [showReportForm, setShowReportForm] = useState(false);

return (
<>
{inventoryReportsEnabled && library && (
<InventoryReportRequestModal
show={showReportForm}
onHide={() => setShowReportForm(false)}
library={library}
/>
)}
<StatsGroup
heading="Inventory"
description="Real-time item inventory."
headingAdditionalContent={
inventoryReportsEnabled &&
library && (
<Button
callback={(() => setShowReportForm(true)) as any}
content="⬇︎"
title="Request an inventory report"
style={{
borderRadius: "50%",
marginLeft: "10px",
marginBottom: "0",
marginTop: "-0.7rem",
}}
className="inline small"
disabled={showReportForm}
/>
)
}
>
<ul>
<SingleStatListItem
label={inventoryKeyToLabelMap.titles}
value={inventory.titles}
tooltip="Total number of books."
/>
<SingleStatListItem
label={inventoryKeyToLabelMap.availableTitles}
value={inventory.availableTitles}
tooltip="Number of books available for lending."
/>
<SingleStatListItem
label={inventoryKeyToLabelMap.meteredLicenseTitles}
value={inventory.meteredLicenseTitles}
tooltip="Number of books with a metered (counted) license."
/>
<SingleStatListItem
label={inventoryKeyToLabelMap.unlimitedLicenseTitles}
value={inventory.unlimitedLicenseTitles}
tooltip="Number of books for which there is no limit on the number of loans."
/>
<SingleStatListItem
label={inventoryKeyToLabelMap.openAccessTitles}
value={inventory.openAccessTitles}
tooltip="Number of books for which there are no limits on use."
/>
</ul>
</StatsGroup>
</>
);
};

const renderConfiguredCollections = (
collections: CollectionInventory[],
showBarchart: boolean
) => {
const content =
collections.length === 0 ? (
<span className="no-collections">No associated collections.</span>
) : showBarchart ? (
<StatsCollectionsBarChart collections={collections} />
) : (
<StatsCollectionsList collections={collections} />
);
const description = `
The following collections are configured in your library's
implementation of the Palace system and are available to your users
through the Palace app.
`;
return (
<StatsGroup heading="Configured Collections" description={description}>
{content}
</StatsGroup>
);
};

export default LibraryStats;
36 changes: 36 additions & 0 deletions src/components/StatsCollectionsGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React = require("react");
import StatsGroup from "./StatsGroup";
import SingleStatListItem from "./SingleStatListItem";
import { CollectionInventory } from "../interfaces";
import StatsCollectionsBarChart from "./StatsCollectionsBarChart";
import StatsCollectionsList from "./StatsCollectionsList";

type Props = {
heading?: string;
description?: string;
collections: CollectionInventory[];
showBarChart: boolean;
};

const StatsCollectionsGroup = ({
heading = "Collections",
description = "Collections configured for your library(ies) in the Palace System.",
collections,
showBarChart,
}: Props) => {
const content =
collections.length === 0 ? (
<span className="no-collections">No associated collections.</span>
) : showBarChart ? (
<StatsCollectionsBarChart collections={collections} />
) : (
<StatsCollectionsList collections={collections} />
);
return (
<StatsGroup heading={heading} description={description}>
{content}
</StatsGroup>
);
};

export default StatsCollectionsGroup;
90 changes: 90 additions & 0 deletions src/components/StatsInventoryGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React = require("react");
import { Button } from "library-simplified-reusable-components";
import StatsGroup from "./StatsGroup";
import SingleStatListItem from "./SingleStatListItem";
import { InventoryStatistics } from "../interfaces";
import InventoryReportRequestModal from "./InventoryReportRequestModal";
import { inventoryKeyToLabelMap } from "./LibraryStats";
import { useState } from "react";

type Props = {
heading?: string;
description?: string;
inventory: InventoryStatistics;
inventoryReportsEnabled: boolean;
library?: string;
};

const StatsInventoryGroup = ({
heading = "Inventory",
description = "Real-time item inventory.",
inventory,
inventoryReportsEnabled,
library = undefined,
}: Props) => {
const [showReportForm, setShowReportForm] = useState(false);

return (
<>
{inventoryReportsEnabled && library && (
<InventoryReportRequestModal
show={showReportForm}
onHide={() => setShowReportForm(false)}
library={library}
/>
)}
<StatsGroup
heading={heading}
description={description}
headingAdditionalContent={
inventoryReportsEnabled &&
library && (
<Button
callback={(() => setShowReportForm(true)) as any}
content="⬇︎"
title="Request an inventory report"
style={{
borderRadius: "50%",
marginLeft: "10px",
marginBottom: "0",
marginTop: "-0.7rem",
}}
className="inline small"
disabled={showReportForm}
/>
)
}
>
<ul>
<SingleStatListItem
label={inventoryKeyToLabelMap.titles}
value={inventory.titles}
tooltip="Total number of books."
/>
<SingleStatListItem
label={inventoryKeyToLabelMap.availableTitles}
value={inventory.availableTitles}
tooltip="Number of books available for lending."
/>
<SingleStatListItem
label={inventoryKeyToLabelMap.meteredLicenseTitles}
value={inventory.meteredLicenseTitles}
tooltip="Number of books with a metered (counted) license."
/>
<SingleStatListItem
label={inventoryKeyToLabelMap.unlimitedLicenseTitles}
value={inventory.unlimitedLicenseTitles}
tooltip="Number of books for which there is no limit on the number of loans."
/>
<SingleStatListItem
label={inventoryKeyToLabelMap.openAccessTitles}
value={inventory.openAccessTitles}
tooltip="Number of books for which there are no limits on use."
/>
</ul>
</StatsGroup>
</>
);
};

export default StatsInventoryGroup;
45 changes: 45 additions & 0 deletions src/components/StatsPatronGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React = require("react");
import StatsGroup from "./StatsGroup";
import SingleStatListItem from "./SingleStatListItem";

type Props = {
heading?: string;
description?: string;
total?: number;
withActiveLoan: number;
withActiveLoanOrHold: number;
};

const StatsPatronGroup = ({
heading = "Patrons",
description = "Real-time patron information for the Palace System.",
total = undefined,
withActiveLoan,
withActiveLoanOrHold,
}: Props) => {
return (
<StatsGroup heading={heading} description={description}>
<ul>
{total && (
<SingleStatListItem
label="Total Patrons"
value={total}
tooltip="Total number of patrons in the Palace System."
/>
)}
<SingleStatListItem
label="Patrons With Active Loans"
value={withActiveLoan}
tooltip="Number of patrons with at least one active loan."
/>
<SingleStatListItem
label="Patrons With Active Loans or Holds"
value={withActiveLoanOrHold}
tooltip="Number of patrons with at least one active loan or at least one hold."
/>
</ul>
</StatsGroup>
);
};

export default StatsPatronGroup;
Loading

0 comments on commit 8b79974

Please sign in to comment.