Skip to content

Commit

Permalink
Fetch data at page and pass merged widget data down props
Browse files Browse the repository at this point in the history
  • Loading branch information
timmo001 committed May 27, 2023
1 parent 70142fa commit 744c832
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 122 deletions.
20 changes: 18 additions & 2 deletions src/app/dashboards/[dashboardId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import type { Metadata } from "next";
import { notFound } from "next/navigation";

import type { DashboardModel } from "@/types/dashboard.type";
import type { SectionModel } from "@/types/section.type";
import { Dashboard } from "@/components/dashboard/views/Dashboard";
import { prisma } from "@/utils/prisma";
import { Section } from "@/components/dashboard/views/Section";
import { widgetGetData } from "@/utils/serverActions/widget";

export const metadata: Metadata = {
title: "Dashboard | Home Panel",
Expand All @@ -23,7 +26,7 @@ export default async function Page({
* The dashboard object retrieved from the database.
* Contains all the sections and widgets associated with the dashboard.
*/
const dashboard: DashboardModel | null = await prisma.dashboard.findUnique({
let dashboard: DashboardModel | null = await prisma.dashboard.findUnique({
where: {
id: params.dashboardId,
},
Expand All @@ -44,5 +47,18 @@ export default async function Page({

if (!dashboard) return notFound();

return <Dashboard dashboard={dashboard} />;
// Fetch data for all widgets
for (const section of dashboard.sections) {
for (const widget of section.widgets) {
widget.data = await widgetGetData(widget.id, widget.type);
}
}

return (
<Dashboard dashboard={dashboard}>
{dashboard.sections.map((section: SectionModel) => (
<Section key={section.id} data={section} />
))}
</Dashboard>
);
}
8 changes: 3 additions & 5 deletions src/components/dashboard/views/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
import { Unstable_Grid2 as Grid2, Stack } from "@mui/material";

import type { DashboardModel } from "@/types/dashboard.type";
import type { SectionModel } from "@/types/section.type";
import { Heading } from "@/components/dashboard/views/Heading";
import { HomeAssistantProvider } from "@/providers/HomeAssistantProvider";
import { Section } from "@/components/dashboard/views/Section";

export function Dashboard({
children,
dashboard,
}: {
children: React.ReactNode;
dashboard: DashboardModel;
}): JSX.Element {
return (
Expand Down Expand Up @@ -39,9 +39,7 @@ export function Dashboard({
maxHeight: "100%",
}}
>
{dashboard.sections.map((section: SectionModel) => (
<Section key={section.id} data={section} />
))}
{children}
</Grid2>
</Stack>
</HomeAssistantProvider>
Expand Down
67 changes: 23 additions & 44 deletions src/components/dashboard/views/Widget.tsx
Original file line number Diff line number Diff line change
@@ -1,122 +1,101 @@
"use client";
import type { Widget as WidgetModel } from "@prisma/client";
import { Skeleton } from "@mui/material";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useCallback, useMemo, useState } from "react";
import { useRouter } from "next/navigation";

import { WidgetBase } from "@/components/dashboard/views/widgets/Base";
import {
widgetDelete,
widgetGetData,
widgetUpdate,
} from "@/utils/serverActions/widget";
import type { WidgetModel } from "@/types/widget.type";
import { WidgetAction, WidgetType } from "@/types/widget.type";
import { WidgetBase } from "@/components/dashboard/views/widgets/Base";
import { WidgetChecklist } from "@/components/dashboard/views/widgets/Checklist";
import { widgetDelete, widgetUpdate } from "@/utils/serverActions/widget";
import { WidgetFrame } from "@/components/dashboard/views/widgets/Frame";
import { WidgetHomeAssistant } from "@/components/dashboard/views/widgets/HomeAssistant";
import { WidgetImage } from "@/components/dashboard/views/widgets/Image";
import { WidgetMarkdown } from "@/components/dashboard/views/widgets/Markdown";

export function Widget({
dashboardId,
data,
editing,
data,
}: {
dashboardId: string;
data: WidgetModel;
dashboardId: string;
editing: boolean;
}): JSX.Element {
const { id, position, sectionId, type } = data;
const [expanded, setExpanded] = useState<boolean>(false);
const [widgetData, setWidgetData] = useState<any>(null);
const router = useRouter();

useEffect(() => {
(async () => {
const newData = await widgetGetData(data.id, data.type);
setWidgetData(newData);
})();
}, [data.id, data.type]);

const handleInteraction = useCallback(
async (action: WidgetAction): Promise<void> => {
console.log("Handle interaction:", action);

switch (action) {
case WidgetAction.Delete:
await widgetDelete(dashboardId, data.id);
await widgetDelete(dashboardId, id);
break;
case WidgetAction.Edit:
router.push(
`/dashboards/${dashboardId}/sections/${data.sectionId}/widgets/${data.id}/edit`
`/dashboards/${dashboardId}/sections/${sectionId}/widgets/${id}/edit`
);
break;
case WidgetAction.MoveDown:
await widgetUpdate(
dashboardId,
data.id,
"position",
data.position + 15
);
await widgetUpdate(dashboardId, id, "position", position + 15);
break;
case WidgetAction.MoveUp:
await widgetUpdate(
dashboardId,
data.id,
"position",
data.position - 15
);
await widgetUpdate(dashboardId, id, "position", position - 15);
break;
case WidgetAction.ToggleExpanded:
setExpanded(!expanded);
break;
}
},
[dashboardId, data.id, data.position, data.sectionId, expanded, router]
[dashboardId, id, position, sectionId, expanded, router]
);

const widgetView: JSX.Element = useMemo(() => {
if (!widgetData) return <Skeleton variant="text" />;
switch (data.type) {
if (!data) return <Skeleton variant="text" />;
switch (type) {
case WidgetType.Checklist:
return (
<WidgetChecklist
dashboardId={dashboardId}
data={widgetData}
sectionId={data.sectionId}
sectionId={sectionId}
widget={data}
/>
);
case WidgetType.Frame:
return <WidgetFrame data={widgetData} />;
return <WidgetFrame widget={data} />;
case WidgetType.HomeAssistant:
return (
<WidgetHomeAssistant
data={widgetData}
editing={editing}
expanded={expanded}
widget={data}
handleInteraction={handleInteraction}
/>
);
case WidgetType.Image:
return (
<WidgetImage
data={widgetData}
editing={editing}
widget={data}
handleInteraction={handleInteraction}
/>
);
case WidgetType.Markdown:
return <WidgetMarkdown data={widgetData} />;
return <WidgetMarkdown widget={data} />;
default:
return <div>Unknown widget type</div>;
}
}, [
dashboardId,
data.sectionId,
data.type,
data,
editing,
expanded,
handleInteraction,
widgetData,
sectionId,
type,
]);

return (
Expand Down
55 changes: 25 additions & 30 deletions src/components/dashboard/views/widgets/Checklist.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,24 @@ import {
AddRounded,
} from "@mui/icons-material";
import { useRouter } from "next/navigation";
import { useState, useTransition } from "react";
import { useState } from "react";

import { WidgetChecklistModel } from "@/types/widget.type";
import type { WidgetChecklistModel, WidgetModel } from "@/types/widget.type";
import { widgetChecklistUpdate } from "@/utils/serverActions/widget";

function WidgetChecklistItem({
dashboardId,
data,
item,
sectionId,
handleDeleted,
}: {
dashboardId: string;
data: WidgetChecklistItemModel;
item: WidgetChecklistItemModel;
sectionId: string;
handleDeleted: () => void;
}): JSX.Element {
const { id, checklistWidgetId, content } = data;
const [checked, setChecked] = useState<boolean>(data.checked);
const { id, checklistWidgetId, content } = item;
const [checked, setChecked] = useState<boolean>(item.checked);
return (
<Grid2>
<TextField
Expand Down Expand Up @@ -104,34 +104,29 @@ function WidgetChecklistItem({

export function WidgetChecklist({
dashboardId,
data,
sectionId,
widget,
}: {
dashboardId: string;
data: WidgetChecklistModel;
sectionId: string;
widget: WidgetModel<WidgetChecklistModel>;
}): JSX.Element {
const [isPending, startTransition] = useTransition();
const router = useRouter();
return (
<Grid2 container direction="column">
{isPending ? (
<></>
) : (
data.items.map((item: WidgetChecklistItemModel) => (
<WidgetChecklistItem
key={item.id}
dashboardId={dashboardId}
data={item}
sectionId={sectionId}
handleDeleted={() => {
startTransition(() => {
router.refresh();
});
}}
/>
))
)}
{widget.data.items.map((item: WidgetChecklistItemModel) => (
<WidgetChecklistItem
key={item.id}
dashboardId={dashboardId}
item={item}
sectionId={sectionId}
handleDeleted={() => {
// startTransition(() => {
// router.refresh();
// });
}}
/>
))}
<Grid2>
<Button
fullWidth
Expand All @@ -141,14 +136,14 @@ export function WidgetChecklist({
await widgetChecklistUpdate(
dashboardId,
sectionId,
data.widgetId,
widget.id,
"",
"content",
""
);
startTransition(() => {
router.refresh();
});
// startTransition(() => {
// router.refresh();
// });
}}
>
<AddRounded />
Expand Down
13 changes: 10 additions & 3 deletions src/components/dashboard/views/widgets/Frame.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
"use client";
import type { WidgetFrame as WidgetFrameModel } from "@prisma/client";

export function WidgetFrame({ data }: { data: WidgetFrameModel }): JSX.Element {
import type { WidgetModel } from "@/types/widget.type";

export function WidgetFrame({
widget,
}: {
widget: WidgetModel<WidgetFrameModel>;
}): JSX.Element {
const { height, url } = widget.data;
return (
<iframe
src={data.url}
src={url}
width="100%"
height={data.height || "100%"}
height={height || "100%"}
style={{
backgroundColor: "transparent",
border: "none",
Expand Down
Loading

0 comments on commit 744c832

Please sign in to comment.