Skip to content

Commit

Permalink
Add edit questionnaire
Browse files Browse the repository at this point in the history
  • Loading branch information
olimsaidov committed Nov 22, 2024
1 parent 5c8ce08 commit 8264240
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { getCurrentAidbox } from "@/lib/server/smart";
import { PageHeader } from "@/components/page-header";
import { Questionnaire } from "fhir/r4";
import { QuestionnaireEditor } from "@/components/questionnaire-editor";

interface PageProps {
params: Promise<{
id: string;
}>;
}

export default async function QuestionnairesPage({ params }: PageProps) {
const aidbox = await getCurrentAidbox();
const { id } = await params;

const questionnaire = await aidbox
.get(`fhir/Questionnaire/${id}`, {})
.json<Questionnaire>();

async function saveQuestionnaire(questionnaire: Questionnaire) {
"use server";

const aidbox = await getCurrentAidbox();
return aidbox
.put(`fhir/Questionnaire/${id}`, {
json: questionnaire,
})
.json<Questionnaire>();
}

return (
<>
<PageHeader
items={[
{ href: "/", label: "Home" },
{ href: "/questionnaires", label: "Questionnaires" },
{ label: "Editor" },
]}
/>
<QuestionnaireEditor
questionnaire={questionnaire}
onSaveAction={saveQuestionnaire}
/>
</>
);
}
57 changes: 57 additions & 0 deletions aidbox-forms-smart-launch-2/src/components/forms-builder.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"use client";

import { useEffect, useRef } from "react";
import { useAwaiter } from "@/hooks/use-awaiter";
import { Questionnaire } from "fhir/r4";

export function FormsBuilder({
questionnaire,
onChange,
}: {
questionnaire: Questionnaire;
onChange?: (questionnaire: Questionnaire) => void;
}) {
const ref = useRef<HTMLIFrameElement>(null);

useEffect(() => {
const current = ref.current;

if (current) {
const handler = (e: Event) => {
onChange?.((e as CustomEvent<Questionnaire>).detail);
};

current.addEventListener("change", handler);

return () => {
current.removeEventListener("change", handler);
};
}
}, [onChange]);

useAwaiter(ref);

return (
<aidbox-form-builder
hide-back={true}
show-share={false}
hide-population={true}
hide-extraction={true}
hide-publish={true}
hide-add-theme={true}
hide-edit-theme={true}
hide-save-theme={true}
hide-convert={true}
hide-save={true}
disable-save={true}
ref={ref}
value={JSON.stringify(questionnaire)}
style={{
width: "100%",
height: "100%",
border: "none",
flex: 1,
}}
/>
);
}
6 changes: 3 additions & 3 deletions aidbox-forms-smart-launch-2/src/components/forms-renderer.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useEffect, useRef } from "react";
import { useAwaiter } from "@/hooks/use-awaiter";
import { Questionnaire } from "fhir/r4";
import { Questionnaire, QuestionnaireResponse } from "fhir/r4";

export function FormsRenderer({
questionnaire,
onChange,
}: {
questionnaire: Questionnaire;
onChange?: (questionnaire: Questionnaire) => void;
onChange?: (questionnaireResponse: QuestionnaireResponse) => void;
}) {
const ref = useRef<HTMLIFrameElement>(null);

Expand All @@ -16,7 +16,7 @@ export function FormsRenderer({

if (current) {
const handler = (e: Event) => {
onChange?.((e as CustomEvent<Questionnaire>).detail);
onChange?.((e as CustomEvent<QuestionnaireResponse>).detail);
};

current.addEventListener("change", handler);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"use client";

import { FormsBuilder } from "@/components/forms-builder";
import { Questionnaire } from "fhir/r4";
import { Suspense, useTransition } from "react";
import { Spinner } from "@/components/spinner";

interface QuestionnaireEditorProps {
questionnaire: Questionnaire;
onSaveAction: (questionnaire: Questionnaire) => Promise<Questionnaire>;
}

export function QuestionnaireEditor({
questionnaire,
onSaveAction,
}: QuestionnaireEditorProps) {
const [, startTransition] = useTransition();

return (
<Suspense fallback={<Spinner expand="true" />}>
<FormsBuilder
questionnaire={questionnaire}
onChange={(updatedQuestionnaire) => {
startTransition(async () => {
try {
await onSaveAction(updatedQuestionnaire);
} catch (error) {
console.error("Failed to save questionnaire:", error);
}
});
}}
/>
</Suspense>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export function QuestionnairesActions({
<DialogTitle>Preview</DialogTitle>
</DialogHeader>
{viewing && (
<Suspense fallback={<Spinner expand={true} />}>
<Suspense fallback={<Spinner expand="true" />}>
<FormsRenderer
questionnaire={questionnaire}
onChange={() => {
Expand Down
2 changes: 1 addition & 1 deletion aidbox-forms-smart-launch-2/src/components/spinner.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type SVGProps } from "react";

export function Spinner(props: SVGProps<SVGSVGElement> & { expand?: boolean }) {
export function Spinner(props: SVGProps<SVGSVGElement> & { expand?: string }) {
const svg = (
<svg
xmlns="http://www.w3.org/2000/svg"
Expand Down
17 changes: 17 additions & 0 deletions aidbox-forms-smart-launch-2/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,23 @@ declare global {
> & {
questionnaire?: string;
};
"aidbox-form-builder": React.DetailedHTMLProps<
React.IframeHTMLAttributes<HTMLIFrameElement>,
HTMLIFrameElement
> & {
"hide-back"?: boolean;
"show-share"?: boolean;
"hide-population"?: boolean;
"hide-extraction"?: boolean;
"hide-publish"?: boolean;
"hide-add-theme"?: boolean;
"hide-edit-theme"?: boolean;
"hide-save-theme"?: boolean;
"hide-convert"?: boolean;
"hide-save"?: boolean;
"disable-save"?: boolean;
value?: string;
};
}
}
}

0 comments on commit 8264240

Please sign in to comment.