Skip to content

Instantly share code, notes, and snippets.

@AlexandroMtzG
Created May 2, 2023 19:02
Show Gist options
  • Save AlexandroMtzG/4126c495c3bd29343f6cdbc83147c617 to your computer and use it in GitHub Desktop.
Save AlexandroMtzG/4126c495c3bd29343f6cdbc83147c617 to your computer and use it in GitHub Desktop.
import { json, LoaderFunction, V2_MetaFunction } from "@remix-run/node";
import { useLoaderData, useSearchParams } from "@remix-run/react";
import { useAppData } from "~/utils/data/useAppData";
import { DashboardLoaderData, loadDashboardData } from "~/utils/data/useDashboardData";
import { i18nHelper } from "~/locale/i18n.utils";
import { getAppDashboardStats } from "~/utils/services/appDashboardService";
import ProfileBanner from "~/components/app/ProfileBanner";
import { DashboardStats } from "~/components/ui/stats/DashboardStats";
import { getTenantIdFromUrl } from "~/utils/services/urlService";
import { Stat } from "~/application/dtos/stats/Stat";
import InputSelector from "~/components/ui/input/InputSelector";
import PeriodHelper, { defaultPeriodFilter, PeriodFilters } from "~/utils/helpers/PeriodHelper";
import { useTranslation } from "react-i18next";
import ServerError from "~/components/ui/errors/ServerError";
import { getServerTiming } from "~/utils/performance/timing.server";
import { serverTimingHeaders } from "~/utils/performance/defaults.server";
export { serverTimingHeaders as headers };
type LoaderData = DashboardLoaderData & {
title: string;
stats: Stat[];
};
export let loader: LoaderFunction = async ({ request, params }) => {
const { time, getServerTimingHeader } = getServerTiming();
let { t } = await time("i18nHelper", i18nHelper(request));
const tenantId = await time("getTenantIdFromUrl", getTenantIdFromUrl(params));
const stats = await time("getAppDashboardStats", getAppDashboardStats({ t, tenantId, gte: PeriodHelper.getGreaterThanOrEqualsFromRequest({ request }) }));
const data: LoaderData = {
title: `${t("app.sidebar.dashboard")} | ${process.env.APP_NAME}`,
...(await time("loadDashboardData", loadDashboardData(params))),
stats,
};
return json(data, { headers: getServerTimingHeader() });
};
export const meta: V2_MetaFunction = ({ data }) => [{ title: data?.title }];
export default function DashboardRoute() {
const { t } = useTranslation();
const appData = useAppData();
const data = useLoaderData<LoaderData>();
const [searchParams, setSearchParams] = useSearchParams();
return (
<main className="relative z-0 flex-1 overflow-y-auto pb-8">
{/*Page header */}
<div className="hidden bg-white shadow md:block lg:border-t lg:border-gray-200">
<ProfileBanner user={appData.user} />
</div>
<div className="mx-auto grid h-screen max-w-5xl gap-5 px-4 py-5 sm:px-8">
{appData.permissions.includes("app.dashboard.view") ? (
<div className="space-y-3">
<div className="flex items-center justify-between space-x-2">
<h3 className="flex-grow font-medium leading-4 text-gray-900">{t("app.dashboard.summary")}</h3>
<div>
<InputSelector
className="w-44"
withSearch={false}
name="period"
value={searchParams.get("period")?.toString() ?? defaultPeriodFilter}
options={PeriodFilters.map((f) => {
return {
value: f.value,
name: t(f.name),
};
})}
setValue={(value) => {
if (value) {
searchParams.set("period", value?.toString() ?? "");
} else {
searchParams.delete("period");
}
setSearchParams(searchParams);
}}
/>
</div>
</div>
<DashboardStats items={data.stats} />
</div>
) : (
<div className="font-medium">You don't have permission to view the dashboard.</div>
)}
</div>
</main>
);
}
export function ErrorBoundary() {
return <ServerError />;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment