-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Form for external survey responses (#79)
- Loading branch information
Showing
16 changed files
with
380 additions
and
14 deletions.
There are no files selected for viewing
5 changes: 5 additions & 0 deletions
5
db/migrations/20240109075002_surveyresponse_add_field_source/migration.sql
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,5 @@ | ||
-- CreateEnum | ||
CREATE TYPE "SurveyResponseSourceEnum" AS ENUM ('EMAIL', 'LETTER', 'FORM'); | ||
|
||
-- AlterTable | ||
ALTER TABLE "SurveyResponse" ADD COLUMN "source" "SurveyResponseSourceEnum" NOT NULL DEFAULT 'FORM'; |
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
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,53 @@ | ||
import { Dialog, Transition } from "@headlessui/react" | ||
import clsx from "clsx" | ||
import { Fragment } from "react" | ||
|
||
type Props = { | ||
children?: React.ReactNode | ||
open: boolean | ||
handleClose: () => void | ||
className?: string | ||
} | ||
|
||
export const Modal: React.FC<Props> = ({ children, open, handleClose, className }) => { | ||
return ( | ||
<Transition.Root show={open} as={Fragment}> | ||
<Dialog as="div" className="relative z-20" onClose={handleClose}> | ||
<Transition.Child | ||
as={Fragment} | ||
enter="ease-out duration-300" | ||
enterFrom="opacity-0" | ||
enterTo="opacity-100" | ||
leave="ease-in duration-200" | ||
leaveFrom="opacity-100" | ||
leaveTo="opacity-0" | ||
> | ||
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" /> | ||
</Transition.Child> | ||
|
||
<div className="fixed inset-0 z-10 w-screen overflow-y-auto"> | ||
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0"> | ||
<Transition.Child | ||
as={Fragment} | ||
enter="ease-out duration-300" | ||
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" | ||
enterTo="opacity-100 translate-y-0 sm:scale-100" | ||
leave="ease-in duration-200" | ||
leaveFrom="opacity-100 translate-y-0 sm:scale-100" | ||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" | ||
> | ||
<Dialog.Panel | ||
className={clsx( | ||
"relative transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-sm sm:p-6", | ||
className, | ||
)} | ||
> | ||
<div className="mt-5 sm:mt-6">{children}</div> | ||
</Dialog.Panel> | ||
</Transition.Child> | ||
</div> | ||
</div> | ||
</Dialog> | ||
</Transition.Root> | ||
) | ||
} |
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
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
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
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
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
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
78 changes: 78 additions & 0 deletions
78
src/survey-responses/components/feedback/ExternalSurveyResponseForm.tsx
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,78 @@ | ||
import { MapProvider } from "react-map-gl" | ||
import { | ||
Form, | ||
FormProps, | ||
LabeledRadiobuttonGroup, | ||
LabeledSelect, | ||
LabeledTextareaField, | ||
} from "src/core/components/forms" | ||
import { H2 } from "src/core/components/text" | ||
import { TMapProps, TResponse } from "src/survey-public/components/types" | ||
|
||
import { z } from "zod" | ||
import { ExternalSurveyResponseFormMap } from "./ExternalSurveyResponseFormMap" | ||
|
||
export { FORM_ERROR } from "src/core/components/forms" | ||
|
||
export function ExternalSurveyResponseForm<S extends z.ZodType<any, any>>( | ||
props: FormProps<S> & { | ||
mapProps: TMapProps | ||
categories: TResponse[] | ||
isLocation: boolean | ||
setIsLocation: any | ||
}, | ||
) { | ||
const { mapProps, categories, isLocation, setIsLocation } = props | ||
|
||
return ( | ||
<Form<S> {...props}> | ||
<H2>Neuen Hinweis erfassen</H2> | ||
<p> | ||
Hier können Sie die Beiträge erfassen, die abseits der Online-Beteiligung eingereicht | ||
wurden. | ||
</p> | ||
|
||
<LabeledRadiobuttonGroup | ||
label="Bezieht sich das Feedback auf eine konkrete Stelle entlang der Route?" | ||
scope="isLocation" | ||
items={[ | ||
{ value: "true", label: "Ja" }, | ||
{ value: "false", label: "Nein" }, | ||
]} | ||
/> | ||
|
||
<MapProvider> | ||
<ExternalSurveyResponseFormMap | ||
isLocation={isLocation} | ||
setIsLocation={setIsLocation} | ||
mapProps={mapProps} | ||
/> | ||
</MapProvider> | ||
|
||
<LabeledTextareaField | ||
className="h-28" | ||
label="Hinweistext" | ||
placeholder="Hinweis hier einfügen..." | ||
name="userText1" | ||
/> | ||
|
||
<LabeledSelect | ||
name="source" | ||
label="Eingereicht" | ||
options={[ | ||
["EMAIL", "per E-Mail"], | ||
["LETTER", "per Brief"], | ||
]} | ||
/> | ||
|
||
<LabeledRadiobuttonGroup | ||
label="Kategorie" | ||
scope="categoryId" | ||
classNameItemWrapper="sm:columns-2" | ||
items={categories.map((category) => { | ||
return { value: String(category.id), label: category.text.de } | ||
})} | ||
/> | ||
</Form> | ||
) | ||
} |
42 changes: 42 additions & 0 deletions
42
src/survey-responses/components/feedback/ExternalSurveyResponseFormMap.tsx
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,42 @@ | ||
import { useState } from "react" | ||
import { useFormContext } from "react-hook-form" | ||
import { SurveyMap } from "src/survey-public/components/maps/SurveyMap" | ||
import { TMapProps } from "src/survey-public/components/types" | ||
|
||
type Props = { mapProps: TMapProps; isLocation: boolean; setIsLocation: any } | ||
|
||
export const ExternalSurveyResponseFormMap: React.FC<Props> = ({ | ||
mapProps, | ||
isLocation, | ||
setIsLocation, | ||
}) => { | ||
const { watch } = useFormContext() | ||
// the isMapDirty state is useless atm - we just need it as a prop for surveyMap but we do not use it here (yet) | ||
const [isMapDirty, setIsMapDirty] = useState(false) | ||
|
||
setIsLocation(watch("isLocation") === "true") | ||
console.log("isMap", isLocation) | ||
|
||
if (!isLocation) return | ||
|
||
return ( | ||
<div> | ||
<p className="mb-4 block text-sm font-medium text-gray-700">Position wählen</p> | ||
<SurveyMap | ||
className="!h-64" | ||
projectMap={{ | ||
maptilerStyleUrl: mapProps.maptilerStyleUrl, | ||
initialMarker: { | ||
lng: mapProps.marker!.lng, | ||
lat: mapProps.marker!.lat, | ||
}, | ||
config: { | ||
bounds: mapProps.config!.bounds, | ||
pinColor: mapProps.config!.pinColor, | ||
}, | ||
}} | ||
setIsMapDirty={setIsMapDirty} | ||
/> | ||
</div> | ||
) | ||
} |
Oops, something went wrong.