Skip to content

Commit

Permalink
Started refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
n1kPLV committed Sep 2, 2023
1 parent 338c706 commit 3026eb5
Show file tree
Hide file tree
Showing 12 changed files with 326 additions and 378 deletions.
14 changes: 14 additions & 0 deletions Website/src/app/management/components/errorMessage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export function ErrorMessage({ error }: { error: string | undefined }) {
return (
<>
{" "}
{
/* display an error message if there is an error */ error && (
<div className="col-span-8 bg-red-300 border-red-600 text-black rounded p-2 text-center">
{error}
</div>
)
}{" "}
</>
);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Select, { Options, SingleValue } from "react-select";
import { Options, SingleValue } from "react-select";
import { Option } from "@/utils/types";
import { useMemo } from "react";
import { POIIconCommonName, POIIconImg } from "@/utils/common";
import { POITypeIcon, POITypeIconValues } from "@/utils/api";
import Image from "next/image"
import { StyledSelect } from "@/app/management/components/styledSelect";

const POI_ICONS: POITypeIcon[] = Object.values(POITypeIconValues);

Expand All @@ -14,14 +14,12 @@ export default function IconSelection({
currentIcon,
setIcon,
setModified,
className,
id,
name
}: {
currentIcon: POITypeIcon | "";
setIcon: (newIcon: POITypeIcon | "") => void;
setModified?: (modified: boolean) => void;
className?: string;
id: string;
name: string;
}) {
Expand All @@ -32,7 +30,7 @@ export default function IconSelection({
label: (
<div key={i} className={"flex items-center h-20"}>
<div className={"base-20 shrink-0 h-full"}>
<Image src={POIIconImg[i]} alt={POIIconCommonName[i]} className={"h-full"} />
<img src={POIIconImg[i]} alt={POIIconCommonName[i]} className={"h-full"} />
</div>
<div className={"ml-2 grow whitespace-normal"}>{POIIconCommonName[i]}</div>
</div>
Expand Down Expand Up @@ -65,14 +63,5 @@ export default function IconSelection({
}
}

return (
<Select
className={className}
inputId={id}
name={name}
options={iconOptions}
value={icon}
onChange={changeFunction}
/>
);
return <StyledSelect inputId={id} name={name} options={iconOptions} value={icon} onChange={changeFunction} />;
}
37 changes: 37 additions & 0 deletions Website/src/app/management/components/inputWithLabel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { PropsWithChildren } from "react";

/**
* An input element with the corresponding label. The label contents are supplied as a child
*/
export function InputWithLabel({
children,
id,
name,
setModified,
setValue,
value
}: PropsWithChildren<{
id: string;
name: string;
value: string;
setValue: (value: string) => void;
setModified: (modified: boolean) => void;
}>) {
return (
<>
<label htmlFor={id} className={"col-span-3"}>
{children}
</label>
<input
value={value}
id={id}
name={name}
className="col-span-5 border border-gray-500 dark:bg-slate-700 rounded"
onChange={e => {
setValue(e.target.value);
setModified(true);
}}
/>
</>
);
}
49 changes: 49 additions & 0 deletions Website/src/app/management/components/referencedObjectSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { PropsWithChildren, useMemo } from "react";
import { Option } from "@/utils/types";
import { Options } from "react-select";
import { StyledSelect } from "@/app/management/components/styledSelect";

export function ReferencedObjectSelect<ValueType, ObjectType>(
props: PropsWithChildren<{
inputId: string;
name: string;
value: ValueType;
setValue: (newValue: ValueType) => void;
setModified: (modified: boolean) => void;
objects: ObjectType[];
mappingFunction: (object: ObjectType) => Option<ValueType>;
width?: 4 | 5;
}>
) {
const defaultValue: Option<"" | ValueType> = useMemo(() => ({ value: "", label: "[Bitte auswählen]" }), []);
const options: Options<Option<"" | ValueType>> = useMemo(
() => props.objects.map(props.mappingFunction),
[props.objects, props.mappingFunction]
);

const currentSelection = useMemo(
() => options.find(({ value: optValue }) => optValue === props.value) ?? defaultValue,
[options, defaultValue, props.value]
);

return (
<>
<label htmlFor={props.inputId} className={"col-span-3"}>
{props.children}
</label>
<StyledSelect
value={currentSelection}
inputId={props.inputId}
name={props.name}
onChange={e => {
if (e !== null && e.value !== "") {
props.setValue(e.value);
props.setModified(true);
}
}}
options={options}
width={props.width}
/>
</>
);
}
43 changes: 43 additions & 0 deletions Website/src/app/management/components/styledSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import Select, { GroupBase, Props } from "react-select";

export function StyledSelect<
Option = unknown,
IsMulti extends boolean = false,
Group extends GroupBase<Option> = GroupBase<Option>
>(props: Omit<Props<Option, IsMulti, Group>, "className" | "unstyled" | "classNames"> & { width?: 4 | 5 }) {
const spanClass = props.width == 4 ? "col-span-4" : props.width == 5 ? "col-span-5" : "col-span-5";
return (
<Select<Option, IsMulti, Group>
className={`${spanClass} border border-gray-500 dark:bg-slate-700 rounded`}
unstyled={true}
classNames={
/*
The zoom controls of a leaflet map use a z-index of 1000. So to display
the select dropdown in front of the map, we need the z-index to be > 1000.
Unfortunately, react-select sets the z-index to 1, without an obvious way
to change this, so we use an important class.
The same applies to background color, which is why we need to set that one
important for proper dark-mode support...
*/
{
menu: () => "!z-1100 dark:bg-slate-700 bg-white my-2 rounded-md drop-shadow-lg",
valueContainer: () => "mx-3",
dropdownIndicator: () =>
"m-2 text-gray-500 transition-colors hover:dark:text-gray-50 hover:text-gray-950",
indicatorSeparator: () => "bg-gray-200 dark:bg-gray-500 my-2",
menuList: () => "py-1",
option: state => {
if (state.isSelected) {
return "px-3 py-2 dark:bg-blue-200 dark:text-black bg-blue-800 text-white";
} else if (state.isFocused) {
return "px-3 py-2 bg-blue-100 dark:bg-blue-900";
} else {
return "px-3 py-2";
}
}
}
}
{...props}
/>
);
}
19 changes: 19 additions & 0 deletions Website/src/app/management/components/submitButtons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { FormEventHandler } from "react";

export function SubmitButtons({ creating, onDelete }: { creating: boolean; onDelete: FormEventHandler }) {
return (
<>
{/*And finally some buttons to submit the form. The deletion button is only available when an existing vehicle is selected.*/}
<button type={"submit"} className="col-span-8 rounded-full bg-gray-700 text-white">
{creating ? "Hinzufügen" : "Ändern"}
</button>
<button
type={"button"}
className="col-span-8 rounded-full disabled:bg-gray-300 bg-gray-700 text-white"
onClick={onDelete}
disabled={creating}>
Löschen
</button>
</>
);
}
Loading

0 comments on commit 3026eb5

Please sign in to comment.