- Added Spanish translations for home page components. - Created API endpoints for fetching home-related data (customers, proformas, issued invoices). - Developed hooks for managing home page data queries. - Implemented home page layout with KPI cards, attention panels, monthly billing summary, and recent activity sections. - Added error handling and loading states for improved user experience.
183 lines
5.7 KiB
TypeScript
183 lines
5.7 KiB
TypeScript
import { useIdentityAuthSession } from "@erp/identity/client";
|
|
import { useCallback, useMemo } from "react";
|
|
|
|
import { useAppTranslation } from "@/locales/i18n";
|
|
|
|
import type {
|
|
HomeAttentionItem,
|
|
HomeKpi,
|
|
HomeProformaStatusSummaryItem,
|
|
} from "../entities/home.entity";
|
|
import { useHomeCustomersTotalQuery } from "../hooks/use-home-customers-total-query";
|
|
import { useHomeMonthlyBillingQuery } from "../hooks/use-home-monthly-billing-query";
|
|
import { useHomeProformasOverviewQuery } from "../hooks/use-home-proformas-overview-query";
|
|
import { useHomeRecentActivityQuery } from "../hooks/use-home-recent-activity-query";
|
|
|
|
export const useHomePageController = () => {
|
|
const { t, i18n } = useAppTranslation();
|
|
const { activeCompany, account } = useIdentityAuthSession();
|
|
const customersTotalQuery = useHomeCustomersTotalQuery();
|
|
const proformasOverviewQuery = useHomeProformasOverviewQuery();
|
|
const monthlyBillingQuery = useHomeMonthlyBillingQuery();
|
|
const recentActivityQuery = useHomeRecentActivityQuery();
|
|
|
|
const kpis = useMemo<HomeKpi[]>(() => {
|
|
const monthlyInvoiceCount = monthlyBillingQuery.data?.invoiceCount ?? 0;
|
|
const openProformasCount = proformasOverviewQuery.data?.openCount ?? 0;
|
|
const readyToIssueCount = proformasOverviewQuery.data?.readyToIssueCount ?? 0;
|
|
const customersTotal = customersTotalQuery.data ?? 0;
|
|
|
|
return [
|
|
{
|
|
id: "customers",
|
|
label: t("web.home.kpis.customers.label"),
|
|
value: new Intl.NumberFormat(i18n.language).format(customersTotal),
|
|
href: "/customers",
|
|
ctaLabel: t("web.home.kpis.customers.cta"),
|
|
},
|
|
{
|
|
id: "open-proformas",
|
|
label: t("web.home.kpis.openProformas.label"),
|
|
value: new Intl.NumberFormat(i18n.language).format(openProformasCount),
|
|
href: "/proformas",
|
|
ctaLabel: t("web.home.kpis.openProformas.cta"),
|
|
},
|
|
{
|
|
id: "ready-to-issue",
|
|
label: t("web.home.kpis.readyToIssue.label"),
|
|
value: new Intl.NumberFormat(i18n.language).format(readyToIssueCount),
|
|
href: "/proformas?status=approved",
|
|
ctaLabel: t("web.home.kpis.readyToIssue.cta"),
|
|
},
|
|
{
|
|
id: "monthly-issued-invoices",
|
|
label: t("web.home.kpis.monthlyIssuedInvoices.label"),
|
|
value: new Intl.NumberFormat(i18n.language).format(monthlyInvoiceCount),
|
|
href: "/customer-invoices",
|
|
ctaLabel: t("web.home.kpis.monthlyIssuedInvoices.cta"),
|
|
},
|
|
];
|
|
}, [
|
|
customersTotalQuery.data,
|
|
i18n.language,
|
|
monthlyBillingQuery.data?.invoiceCount,
|
|
proformasOverviewQuery.data?.openCount,
|
|
proformasOverviewQuery.data?.readyToIssueCount,
|
|
t,
|
|
]);
|
|
|
|
const attentionItems = useMemo<HomeAttentionItem[]>(() => {
|
|
const statusCounts = proformasOverviewQuery.data?.statusCounts;
|
|
|
|
if (!statusCounts) {
|
|
return [];
|
|
}
|
|
|
|
return [
|
|
{
|
|
id: "approved",
|
|
count: statusCounts.approved,
|
|
href: "/proformas?status=approved",
|
|
title: t("web.home.attention.readyToIssue.title"),
|
|
description: t("web.home.attention.readyToIssue.description"),
|
|
},
|
|
{
|
|
id: "sent",
|
|
count: statusCounts.sent,
|
|
href: "/proformas?status=sent",
|
|
title: t("web.home.attention.sent.title"),
|
|
description: t("web.home.attention.sent.description"),
|
|
},
|
|
{
|
|
id: "draft",
|
|
count: statusCounts.draft,
|
|
href: "/proformas?status=draft",
|
|
title: t("web.home.attention.draft.title"),
|
|
description: t("web.home.attention.draft.description"),
|
|
},
|
|
].filter((item) => item.count > 0);
|
|
}, [proformasOverviewQuery.data?.statusCounts, t]);
|
|
|
|
const proformaStatusSummary = useMemo<HomeProformaStatusSummaryItem[]>(() => {
|
|
const statusCounts = proformasOverviewQuery.data?.statusCounts;
|
|
|
|
if (!statusCounts) {
|
|
return [];
|
|
}
|
|
|
|
return [
|
|
{
|
|
id: "draft",
|
|
label: t("web.home.proformas.status.draft"),
|
|
count: statusCounts.draft,
|
|
href: "/proformas?status=draft",
|
|
},
|
|
{
|
|
id: "sent",
|
|
label: t("web.home.proformas.status.sent"),
|
|
count: statusCounts.sent,
|
|
href: "/proformas?status=sent",
|
|
},
|
|
{
|
|
id: "approved",
|
|
label: t("web.home.proformas.status.approved"),
|
|
count: statusCounts.approved,
|
|
href: "/proformas?status=approved",
|
|
},
|
|
{
|
|
id: "rejected",
|
|
label: t("web.home.proformas.status.rejected"),
|
|
count: statusCounts.rejected,
|
|
href: "/proformas?status=rejected",
|
|
},
|
|
{
|
|
id: "issued",
|
|
label: t("web.home.proformas.status.issued"),
|
|
count: statusCounts.issued,
|
|
href: "/proformas?status=issued",
|
|
},
|
|
];
|
|
}, [proformasOverviewQuery.data?.statusCounts, t]);
|
|
|
|
const hasBlockingError =
|
|
customersTotalQuery.isError &&
|
|
proformasOverviewQuery.isError &&
|
|
monthlyBillingQuery.isError &&
|
|
recentActivityQuery.isError;
|
|
|
|
const retry = useCallback(async () => {
|
|
await Promise.all([
|
|
customersTotalQuery.refetch(),
|
|
proformasOverviewQuery.refetch(),
|
|
monthlyBillingQuery.refetch(),
|
|
recentActivityQuery.refetch(),
|
|
]);
|
|
}, [customersTotalQuery, monthlyBillingQuery, proformasOverviewQuery, recentActivityQuery]);
|
|
|
|
const pageError = useMemo(() => {
|
|
if (!hasBlockingError) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
title: t("web.home.errors.blocking.title"),
|
|
description: t("web.home.errors.blocking.description"),
|
|
};
|
|
}, [hasBlockingError, t]);
|
|
|
|
return {
|
|
account,
|
|
activeCompany,
|
|
kpis,
|
|
attentionItems,
|
|
proformaStatusSummary,
|
|
customersTotalQuery,
|
|
proformasOverviewQuery,
|
|
monthlyBillingQuery,
|
|
recentActivityQuery,
|
|
hasBlockingError,
|
|
pageError,
|
|
retry,
|
|
};
|
|
};
|