-
Notifications
You must be signed in to change notification settings - Fork 189
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #512 from Shelf-nu/hunar/dashboard
Dashboard
- Loading branch information
Showing
30 changed files
with
2,022 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { useLoaderData } from "@remix-run/react"; | ||
import type { loader } from "~/routes/_layout+/dashboard"; | ||
import { StarsIcon } from "../icons"; | ||
import { MarkdownViewer } from "../markdown"; | ||
import { Button } from "../shared/button"; | ||
|
||
export default function AnnouncementBar() { | ||
const { announcement } = useLoaderData<typeof loader>(); | ||
return announcement ? ( | ||
<div className="mb:gap-4 mb:p-4 mb-4 flex items-center gap-2 rounded border border-gray-200 px-2 py-3"> | ||
<div className="inline-flex items-center justify-center rounded-full border-[6px] border-solid border-primary-50 bg-primary-100 p-1.5 text-primary"> | ||
<StarsIcon /> | ||
</div> | ||
<div className="flex-1 items-center gap-1.5 xl:flex"> | ||
<div> | ||
<MarkdownViewer content={announcement.content} /> | ||
</div> | ||
</div> | ||
<Button variant="primary" to={announcement.link} className=""> | ||
{announcement.linkText} | ||
</Button> | ||
{/* <Button variant="secondary" className="border-none bg-transparent"> | ||
<XIcon /> | ||
</Button> */} | ||
</div> | ||
) : null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { useLoaderData } from "@remix-run/react"; | ||
import type { Color } from "@tremor/react"; | ||
import { DonutChart } from "@tremor/react"; | ||
import { ClientOnly } from "remix-utils/client-only"; | ||
import type { loader } from "~/routes/_layout+/dashboard"; | ||
import { EmptyState } from "./empty-state"; | ||
import { Badge, Button } from "../shared"; | ||
import { InfoTooltip } from "../shared/info-tooltip"; | ||
|
||
export default function AssetsByCategoryChart() { | ||
const { assetsByCategory } = useLoaderData<typeof loader>(); | ||
const chartColors: Color[] = [ | ||
"slate", | ||
"sky", | ||
"rose", | ||
"orange", | ||
"red", | ||
"purple", | ||
]; | ||
|
||
const correspondingChartColorsHex: string[] = [ | ||
"#64748b", | ||
"#0ea5e9", | ||
"#f43f5e", | ||
"#f97316", | ||
"#ef4444", | ||
"#a855f7", | ||
]; | ||
|
||
return ( | ||
<ClientOnly fallback={null}> | ||
{() => ( | ||
<div className="border border-gray-200"> | ||
<div className="flex items-center justify-between"> | ||
<div className="flex-1 border-b p-4 text-left text-[14px] font-semibold text-gray-900 md:px-6"> | ||
Assets by category (top 6) | ||
</div> | ||
<div className="border-b p-4 text-right text-[14px] font-semibold text-gray-900 md:px-6"> | ||
<InfoTooltip | ||
content={ | ||
<> | ||
<h6>Assets by Category</h6> | ||
<p> | ||
Below graph shows how many percent of assets are in which | ||
category{" "} | ||
</p> | ||
</> | ||
} | ||
/> | ||
</div> | ||
</div> | ||
<div className="h-full p-8"> | ||
{assetsByCategory.length > 0 ? ( | ||
<div className="flex flex-col items-center gap-4 lg:flex-row lg:justify-between"> | ||
<DonutChart | ||
className="mt-6 h-[240px] w-[240px] 2xl:h-[320px] 2xl:w-[320px]" | ||
data={assetsByCategory} | ||
category="assets" | ||
index="category" | ||
showAnimation={true} | ||
animationDuration={400} | ||
colors={chartColors} | ||
/> | ||
<div className="min-w-[140px]"> | ||
<ul className="flex flex-wrap items-center lg:block"> | ||
{assetsByCategory.map((cd, i) => ( | ||
<li className="my-1" key={cd.category}> | ||
<Button | ||
to={`/assets?category=${cd.id}`} | ||
variant="link" | ||
className="border text-gray-700 hover:text-gray-500" | ||
> | ||
<Badge color={correspondingChartColorsHex[i]} noBg> | ||
<span className="text-gray-600"> | ||
<strong className="text-gray-900"> | ||
{cd.assets} | ||
</strong>{" "} | ||
{cd.category} | ||
</span> | ||
</Badge> | ||
</Button> | ||
</li> | ||
))} | ||
<li> | ||
<Button to="/categories" variant="link"> | ||
See all | ||
</Button> | ||
</li> | ||
</ul> | ||
</div> | ||
</div> | ||
) : ( | ||
<EmptyState text="No assets in database" /> | ||
)} | ||
</div> | ||
</div> | ||
)} | ||
</ClientOnly> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { useLoaderData } from "@remix-run/react"; | ||
import { DonutChart } from "@tremor/react"; | ||
import { ClientOnly } from "remix-utils/client-only"; | ||
import type { loader } from "~/routes/_layout+/dashboard"; | ||
import { EmptyState } from "./empty-state"; | ||
import { Badge } from "../shared"; | ||
import { InfoTooltip } from "../shared/info-tooltip"; | ||
|
||
export default function AssetsByStatusChart() { | ||
const { assetsByStatus } = useLoaderData<typeof loader>(); | ||
|
||
const { chartData, availableAssets, inCustodyAssets } = assetsByStatus; | ||
|
||
return ( | ||
<ClientOnly fallback={null}> | ||
{() => ( | ||
<div className="w-full border border-gray-200 "> | ||
<div className="flex items-center justify-between"> | ||
<div className="flex-1 border-b p-4 text-left text-[14px] font-semibold text-gray-900 md:px-6"> | ||
Assets by status | ||
</div> | ||
<div className="border-b p-4 text-right text-[14px] font-semibold text-gray-900 md:px-6"> | ||
<InfoTooltip | ||
content={ | ||
<> | ||
<h6>Assets by Status</h6> | ||
<p> | ||
Below graph shows how many percent of assets are in which | ||
status{" "} | ||
</p> | ||
</> | ||
} | ||
/> | ||
</div> | ||
</div> | ||
<div className="h-full p-8"> | ||
{chartData?.length > 0 ? ( | ||
<div className="flex flex-col items-center gap-4 lg:flex-row lg:justify-between"> | ||
<DonutChart | ||
className="mt-6 h-[240px] w-[240px] 2xl:h-[320px] 2xl:w-[320px]" | ||
data={chartData} | ||
category="assets" | ||
index="status" | ||
colors={["green", "blue"]} | ||
showAnimation={true} | ||
animationDuration={400} | ||
/> | ||
<div className="min-w-[140px]"> | ||
<ul className="flex flex-wrap items-center lg:block"> | ||
<li> | ||
<Badge color="#22c55e" noBg> | ||
<span className="text-gray-600"> | ||
<strong className="text-gray-900"> | ||
{availableAssets} | ||
</strong>{" "} | ||
Available | ||
</span> | ||
</Badge> | ||
</li> | ||
<li> | ||
<Badge color="#3b82f6" noBg> | ||
<span className="text-gray-600"> | ||
<strong className="text-gray-900"> | ||
{inCustodyAssets} | ||
</strong>{" "} | ||
In Custody | ||
</span> | ||
</Badge> | ||
</li> | ||
</ul> | ||
</div> | ||
</div> | ||
) : ( | ||
<EmptyState text="No assets in database" /> | ||
)} | ||
</div> | ||
</div> | ||
)} | ||
</ClientOnly> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { useLoaderData } from "@remix-run/react"; | ||
import { AreaChart, Card, Title } from "@tremor/react"; | ||
import { ClientOnly } from "remix-utils/client-only"; | ||
import type { loader } from "~/routes/_layout+/dashboard"; | ||
import { InfoTooltip } from "../shared/info-tooltip"; | ||
|
||
export default function AssetsForEachMonth() { | ||
const { totalAssetsAtEndOfEachMonth, totalAssets } = | ||
useLoaderData<typeof loader>(); | ||
return ( | ||
<ClientOnly fallback={null}> | ||
{() => ( | ||
<Card className="mb-10 py-4 lg:p-6"> | ||
<Title> | ||
<div className="flex justify-between"> | ||
<div> | ||
<span className="mb-2 block text-[14px] font-medium"> | ||
Total inventory | ||
</span> | ||
<span className="block text-[30px] font-semibold text-gray-900"> | ||
{totalAssets} assets | ||
</span> | ||
</div> | ||
<InfoTooltip | ||
content={ | ||
<> | ||
<h6>Total inventory</h6> | ||
<p> | ||
Below graph shows the total assets you have created in the | ||
last year | ||
</p> | ||
</> | ||
} | ||
/> | ||
</div> | ||
</Title> | ||
<AreaChart | ||
className="mt-4 h-72" | ||
data={totalAssetsAtEndOfEachMonth} | ||
index="month" | ||
categories={["Total assets"]} | ||
colors={["orange"]} | ||
showAnimation={true} | ||
animationDuration={400} | ||
curveType="monotone" | ||
/> | ||
</Card> | ||
)} | ||
</ClientOnly> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import { useLoaderData } from "@remix-run/react"; | ||
import type { TeamMemberWithUser } from "~/modules/team-member/types"; | ||
import type { loader } from "~/routes/_layout+/dashboard"; | ||
import { EmptyState } from "./empty-state"; | ||
import { InfoTooltip } from "../shared/info-tooltip"; | ||
import { Table, Td, Tr } from "../table"; | ||
|
||
export default function CustodiansList() { | ||
const { custodiansData } = useLoaderData<typeof loader>(); | ||
|
||
return ( | ||
<> | ||
<div className="rounded-t border border-b-0 border-gray-200"> | ||
<div className="flex items-center justify-between"> | ||
<div className="flex-1 p-4 text-left text-[14px] font-semibold text-gray-900 md:px-6"> | ||
Custodians | ||
</div> | ||
<div className=" p-4 text-right text-[14px] font-semibold text-gray-900 md:px-6"> | ||
<InfoTooltip | ||
content={ | ||
<> | ||
<h6>Custodians</h6> | ||
<p>Below listed custodians hold the most assets</p> | ||
</> | ||
} | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
{custodiansData.length > 0 ? ( | ||
<Table className="h-full rounded border border-gray-200 p-8"> | ||
<tbody> | ||
{custodiansData.map((cd) => ( | ||
<Tr key={cd.id} className="h-[72px]"> | ||
{/** | ||
* @TODO this needs to be resolved. Its because of the createdAt & updatedAt fields. | ||
* We need a global solution for this as it happens everywhere | ||
* @ts-ignore */} | ||
<Row custodian={cd.custodian} count={cd.count} /> | ||
</Tr> | ||
))} | ||
{custodiansData.length < 5 && | ||
Array(5 - custodiansData.length) | ||
.fill(null) | ||
.map((_d, i) => ( | ||
<Tr key={i} className="h-[72px]"> | ||
{""} | ||
</Tr> | ||
))} | ||
</tbody> | ||
</Table> | ||
) : ( | ||
<div className="h-full flex-1 rounded-b border border-gray-200 p-8"> | ||
<EmptyState text="No assets in custody" /> | ||
</div> | ||
)} | ||
</> | ||
); | ||
} | ||
|
||
function Row({ | ||
custodian, | ||
count, | ||
}: { | ||
custodian: TeamMemberWithUser; | ||
count: number; | ||
}) { | ||
return ( | ||
<> | ||
<Td className="w-full"> | ||
<div className="flex items-center justify-between"> | ||
<span className="text-text-sm font-medium text-gray-900"> | ||
<div className="flex items-center gap-3"> | ||
<img | ||
src={ | ||
custodian?.user?.profilePicture | ||
? custodian?.user?.profilePicture | ||
: "/images/default_pfp.jpg" | ||
} | ||
className={"h-10 w-10 rounded-[4px]"} | ||
alt={`${custodian.name}'s profile`} | ||
/> | ||
<div> | ||
<span className="mt-[1px]">{custodian.name}</span> | ||
<span className="block text-gray-600">{count} Assets</span> | ||
</div> | ||
</div> | ||
</span> | ||
</div> | ||
</Td> | ||
<Td>{""}</Td> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
export function EmptyState({ text }: { text: string }) { | ||
return ( | ||
<div className="flex h-full min-h-[200px] w-full flex-col items-center justify-center"> | ||
<img | ||
src="/images/empty-state.svg" | ||
alt="Empty state" | ||
className="h-auto w-[45px]" | ||
/> | ||
<div className="text-center font-semibold text-gray-900">{text}</div> | ||
</div> | ||
); | ||
} |
Oops, something went wrong.