Skip to content

Commit

Permalink
Refactor FeedbackForm and reuse for interop
Browse files Browse the repository at this point in the history
  • Loading branch information
mpanne committed Feb 13, 2025
1 parent 365b993 commit a4ac4cb
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 122 deletions.
187 changes: 74 additions & 113 deletions packages/dito/app/components/FeedbackForm.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
import Background from "@digitalcheck/shared/components/Background";
import Button from "@digitalcheck/shared/components/Button";
import Container from "@digitalcheck/shared/components/Container";
import RichText from "@digitalcheck/shared/components/RichText";
import ThumbDownOutlined from "@digitalservicebund/icons/ThumbDownOutlined";
import ThumbUpOutlined from "@digitalservicebund/icons/ThumbUpOutlined";
import React, { useEffect, useRef, useState } from "react";
import { feedbackForm } from "resources/content";
import { twJoin } from "tailwind-merge";

type FeedbackQuestionOptionProps = {
label: string;
value: number;
};

type FeedbackQuestionProps = {
id: string;
text: string;
options: FeedbackQuestionOptionProps[];
};

type FeedbackFormProps = {
heading: string;
trackingEvent: string;
questions: FeedbackQuestionProps[];
contact: string;
button: string;
success: {
heading: string;
text: string;
};
};

function FeedbackInput({
children,
value,
Expand All @@ -25,7 +46,7 @@ function FeedbackInput({
ariaLabel: string;
}>) {
const classes = twJoin(
"px-16 h-48 sm:px-24 sm:h-64 flex items-center",
"px-16 h-48 sm:px-24 sm:h-64 flex items-center cursor-pointer",
selected ? "bg-blue-800 text-white" : "bg-blue-200 text-blue-800",
);

Expand All @@ -47,15 +68,9 @@ function FeedbackInput({
}

function FeedbackQuestion({
legend,
isBinary = false,
name,
isLast = false,
question,
}: Readonly<{
legend: string;
isBinary?: boolean;
name: string;
isLast?: boolean;
question: FeedbackQuestionProps;
}>) {
const [selected, setSelected] = useState<number | null>(null);

Expand All @@ -66,110 +81,64 @@ function FeedbackQuestion({
return (
<fieldset
className={twJoin(
"flex flex-col lg:flex-row gap-20 lg:gap-24 pt-24 pb-20 border-blue-300",
!isLast && "border-b-2", // conditional rendering because last:border-b-0 doesn't work here
"flex flex-col lg:flex-row gap-20 lg:gap-24 pt-24 pb-20 border-blue-300 border-b-2 last:border-b-0",
)}
>
<div className="lg:w-1/2">
<legend>
<p>{legend}</p>
<p>{question.text}</p>
</legend>
</div>
<div className="lg:w-1/2">
{isBinary ? (
<div className="flex gap-16">
<FeedbackInput
value={1}
selected={selected === 1}
onChange={onChange}
name={name}
id={`${name}-yes`}
ariaLabel="Ja"
>
<ThumbUpOutlined />
<span className="ds-label-01-bold">Ja</span>
</FeedbackInput>
<FeedbackInput
value={2}
selected={selected === 2}
onChange={onChange}
name={name}
id={`${name}-no`}
ariaLabel="Nein"
>
<ThumbDownOutlined />
<span className="ds-label-01-bold">Nein</span>
</FeedbackInput>
<div className="max-w-fit">
<div className="flex gap-8 sm:gap-16">
{question.options.map(({ value }) => {
return (
<FeedbackInput
key={value}
value={value}
selected={selected === value}
onChange={onChange}
name={question.id}
id={`${question.id}-${value}`}
ariaLabel={`${value}`}
>
<span className="ds-heading-02-reg">{value}</span>
</FeedbackInput>
);
})}
</div>
) : (
<div className="max-w-fit">
<div className="flex gap-8 sm:gap-16">
{[1, 2, 3, 4, 5].map((number) => {
let ariaLabel: string;
switch (number) {
case 1:
ariaLabel = "sehr schwierig";
break;
case 2:
ariaLabel = "schwierig";
break;
case 3:
ariaLabel = "mittel";
break;
case 4:
ariaLabel = "einfach";
break;
case 5:
ariaLabel = "sehr einfach";
break;
default:
ariaLabel = "";
}

return (
<FeedbackInput
key={number}
value={number}
selected={selected === number}
onChange={onChange}
name={name}
id={`${name}-${number}`}
ariaLabel={ariaLabel}
>
<span className="ds-heading-02-reg">{number}</span>
</FeedbackInput>
);
})}
</div>
<div className="mt-20 flex justify-between text-gray-900">
<span className="">{feedbackForm.labels[0]}</span>
<span className="">{feedbackForm.labels[4]}</span>
</div>
<div className="mt-20 flex justify-between text-gray-900">
<span className="">{question.options[0].label}</span>
<span className="">
{question.options[question.options.length - 1].label}
</span>
</div>
)}
</div>
</div>
</fieldset>
);
}

export default function FeedbackForm() {
export default function FeedbackForm(props: FeedbackFormProps) {
const [submitted, setSubmitted] = useState(false);
const thankYouMessageRef = useRef<HTMLDivElement>(null);

const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();

const formData = new FormData(event.currentTarget);
const simpleFeedback = formData.get("simple-feedback");
const usefulFeedback = formData.get("useful-feedback");

// Plausible event trigger with feedback values
if (window.plausible) {
window.plausible("Feedback Methoden", {
props: {
questionSimple: simpleFeedback ?? "No Feedback",
questionUseful: usefulFeedback ?? "No Feedback",
},
const formData = new FormData(event.currentTarget);

const trackingEventProps: { [key: string]: string } = {};
props.questions.forEach((question) => {
trackingEventProps[question.id] =
(formData.get(question.id) as string) ?? "No Feedback";
});

window.plausible(props.trackingEvent, {
props: trackingEventProps,
});
}

Expand All @@ -188,9 +157,9 @@ export default function FeedbackForm() {
<div ref={thankYouMessageRef} tabIndex={-1} aria-live="polite">
<Background backgroundColor="blue" className="pb-48 pt-40">
<Container backgroundColor="white" overhangingBackground>
<h2>{feedbackForm.success.heading}</h2>
<h2>{props.success.heading}</h2>
<br />
<p>{feedbackForm.success.text}</p>
<p>{props.success.text}</p>
</Container>
</Background>
</div>
Expand All @@ -200,25 +169,17 @@ export default function FeedbackForm() {
return (
<Background backgroundColor="blue" className="pb-48 pt-40">
<Container backgroundColor="white" overhangingBackground>
<h2>{feedbackForm.heading}</h2>
<h2>{props.heading}</h2>
<form onSubmit={handleSubmit} className="mb-48">
<FeedbackQuestion
legend={feedbackForm.questionSimple}
name="simple-feedback"
/>
<FeedbackQuestion
legend={feedbackForm.questionUseful}
name="useful-feedback"
isLast={true}
/>
<button
type="submit"
className="mt-16 bg-blue-800 px-24 py-12 text-white"
>
Feedback absenden
</button>
<span>
{props.questions?.length !== 0 &&
props.questions.map((question) => (
<FeedbackQuestion key={question.id} question={question} />
))}
</span>
<Button text={props.button} size="large" type="submit" />
</form>
<RichText markdown={feedbackForm.mail} className="font-bold" />
<RichText markdown={props.contact} className="font-bold" />
</Container>
</Background>
);
Expand Down
59 changes: 52 additions & 7 deletions packages/dito/app/resources/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,18 +279,29 @@ export const supportBanner = {
},
};

export const feedbackForm = {
const feedbackForm = {
heading: "Ihr Feedback hilft uns weiter!",
labels: ["Sehr schwierig", "Schwierig", "Moderat", "Einfach", "Sehr einfach"],
questionSimple:
"Wie einfach war es für Sie, unseren Dienst „Digitaltaugliche Regelungen erarbeiten“ zu nutzen?",
questionUseful:
"Wie hilfreich fanden Sie die angebotenen Methoden und Werkzeuge für das Erarbeiten ihres Regelungsvorhaben?",
mail: "Schreiben Sie uns eine Email an [digitalcheck@digitalservice.bund.de](mailto:digitalcheck@digitalservice.bund.de?subject=Feedback:%20erarbeiten.digitalcheck.bund.de), wenn wir Sie für Feedback zu unserem Service kontaktieren dürfen.",
contact:
"Schreiben Sie uns eine Email an [digitalcheck@digitalservice.bund.de](mailto:digitalcheck@digitalservice.bund.de?subject=Feedback:%20erarbeiten.digitalcheck.bund.de), wenn wir Sie für Feedback zu unserem Service kontaktieren dürfen.",
success: {
heading: "Vielen Dank für Ihr Feedback!",
text: "Wir schätzen Ihre Rückmeldung sehr und werden sie in unsere Verbesserungen einfließen lassen.",
},
button: "Feedback absenden",
optionsSimple: [
{ label: "Sehr schwierig", value: 1 },
{ label: "Schwierig", value: 2 },
{ label: "Moderat", value: 3 },
{ label: "Einfach", value: 4 },
{ label: "Sehr einfach", value: 5 },
],
optionsUseful: [
{ label: "Nicht hilfreich", value: 1 },
{ label: "Wenig hilfreich", value: 2 },
{ label: "Neutral", value: 3 },
{ label: "Hilfreich", value: 4 },
{ label: "Sehr hilfreich", value: 5 },
],
};

export const interviewBanner = {
Expand Down Expand Up @@ -832,6 +843,25 @@ Die Erkenntnisse und Ergebnisse aus den vorigen Schritten helfen Ihnen dabei,
steps.nkr,
],
},
feedbackForm: {
heading: feedbackForm.heading,
trackingEvent: "Feedback Methoden",
questions: [
{
id: "simple-feedback",
text: "Wie einfach war es für Sie, unseren Dienst „Digitaltaugliche Regelungen erarbeiten“ zu nutzen?",
options: feedbackForm.optionsSimple,
},
{
id: "useful-feedback",
text: "Wie hilfreich fanden Sie die angebotenen Methoden und Werkzeuge für das Erarbeiten ihres Regelungsvorhaben?",
options: feedbackForm.optionsUseful,
},
],
contact: feedbackForm.contact,
button: feedbackForm.button,
success: feedbackForm.success,
},
};

export const digitalSuitability = {
Expand Down Expand Up @@ -2130,4 +2160,19 @@ Das Digitalcheck Team unterstützt Sie bei der Erfüllung dieser Anforderungen.
alt: `TODO`, // TODO: provide alt text
},
},
feedbackForm: {
heading: feedbackForm.heading,
trackingEvent: "Feedback Interoperabel Landing Page",
questions: [
{
id: "useful-feedback",
text: "Wie hilfreich waren die Informationen auf der Seite für Sie?",
options: feedbackForm.optionsUseful,
},
],
contact:
"Schreiben Sie uns eine Email an [interoperabel@digitalservice.bund.de](mailto:digitalcheck@digitalservice.bund.de?subject=Feedback:%20erarbeiten.digitalcheck.bund.de), wenn wir Sie für Feedback zu unserem Service kontaktieren dürfen.",
button: feedbackForm.button,
success: feedbackForm.success,
},
};
2 changes: 1 addition & 1 deletion packages/dito/app/routes/interoperabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export default function Interoperability() {
</Link>
</Container>
</div>
<FeedbackForm />
<FeedbackForm {...interoperability.feedbackForm} />
<SupportBanner withFeedbackBanner={false} />
</>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/dito/app/routes/methoden.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default function Methoden() {
items={methods.nextSteps.items}
/>
</Container>
<FeedbackForm />
<FeedbackForm {...methods.feedbackForm} />
<SupportBanner withFeedbackBanner={false} />
</>
);
Expand Down

0 comments on commit a4ac4cb

Please sign in to comment.