2023-08-11 08:30:04 +00:00
|
|
|
import {
|
|
|
|
Autocomplete,
|
|
|
|
Avatar,
|
|
|
|
Box,
|
|
|
|
IconButton,
|
|
|
|
ListItem,
|
|
|
|
ListItemAvatar,
|
|
|
|
ListItemButton,
|
|
|
|
ListItemSecondaryAction,
|
|
|
|
ListItemText,
|
|
|
|
TextField,
|
|
|
|
Typography,
|
|
|
|
autocompleteClasses,
|
|
|
|
} from "@mui/material";
|
|
|
|
import ClearIcon from "@mui/icons-material/Clear";
|
|
|
|
import { Member, fmtDate } from "../../api/MemberApi";
|
|
|
|
import { useFamily } from "../BaseFamilyRoute";
|
|
|
|
import React from "react";
|
|
|
|
import { MemberPhoto } from "../MemberPhoto";
|
|
|
|
import Icon from "@mdi/react";
|
|
|
|
import { mdiCross } from "@mdi/js";
|
|
|
|
import { useNavigate } from "react-router-dom";
|
2023-08-10 12:13:27 +00:00
|
|
|
|
|
|
|
export function MemberInput(p: {
|
|
|
|
editable: boolean;
|
|
|
|
current?: number;
|
|
|
|
onValueChange: (n?: number) => void;
|
|
|
|
label: string;
|
|
|
|
filter: (m: Member) => boolean;
|
|
|
|
}): React.ReactElement {
|
2023-08-11 08:30:04 +00:00
|
|
|
const n = useNavigate();
|
|
|
|
const family = useFamily();
|
|
|
|
|
|
|
|
const choices = family.members.filter(p.filter);
|
|
|
|
|
|
|
|
const [inputValue, setInputValue] = React.useState("");
|
|
|
|
|
|
|
|
if (p.current) {
|
|
|
|
const member = family.members.get(p.current)!;
|
|
|
|
return (
|
|
|
|
<div style={{ display: "flex", alignItems: "center" }}>
|
|
|
|
<Typography variant="body2">{p.label}</Typography>
|
|
|
|
<MemberItem
|
|
|
|
member={member}
|
|
|
|
onClick={
|
|
|
|
!p.editable
|
|
|
|
? () => {
|
|
|
|
n(family.family.URL(`member/${member.id}`));
|
|
|
|
}
|
|
|
|
: undefined
|
|
|
|
}
|
|
|
|
secondary={
|
|
|
|
p.editable ? (
|
|
|
|
<>
|
|
|
|
<IconButton
|
|
|
|
edge="end"
|
|
|
|
onClick={() => p.onValueChange(undefined)}
|
|
|
|
>
|
|
|
|
<ClearIcon />
|
|
|
|
</IconButton>
|
|
|
|
</>
|
|
|
|
) : undefined
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!p.editable) return <></>;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Autocomplete
|
|
|
|
value={p.current ? family.members.get(p.current) : undefined}
|
|
|
|
onChange={(_event: any, newValue: Member | null | undefined) => {
|
|
|
|
p.onValueChange(newValue?.id);
|
|
|
|
}}
|
|
|
|
inputValue={inputValue}
|
|
|
|
onInputChange={(_event, newInputValue) => {
|
|
|
|
setInputValue(newInputValue);
|
|
|
|
}}
|
|
|
|
options={choices}
|
|
|
|
sx={{ width: "100%" }}
|
|
|
|
filterOptions={(options, state) =>
|
|
|
|
options.filter((m) =>
|
|
|
|
m?.fullName.toLowerCase().includes(state.inputValue)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
getOptionLabel={(o) => o?.fullName ?? ""}
|
|
|
|
renderInput={(params) => <TextField {...params} label={p.label} />}
|
|
|
|
renderOption={(_props, option, _state) => (
|
|
|
|
<MemberItem
|
|
|
|
member={option}
|
|
|
|
onClick={() => p.onValueChange(option?.id)}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function MemberItem(p: {
|
|
|
|
member?: Member;
|
|
|
|
onClick?: () => void;
|
|
|
|
secondary?: React.ReactElement;
|
|
|
|
}): React.ReactElement {
|
|
|
|
return (
|
|
|
|
<ListItemButton onClick={p.onClick}>
|
|
|
|
<ListItemAvatar>
|
|
|
|
<MemberPhoto member={p.member!} />
|
|
|
|
</ListItemAvatar>
|
|
|
|
<ListItemText
|
|
|
|
primary={
|
|
|
|
<>
|
|
|
|
{p.member?.fullName}{" "}
|
|
|
|
{p.member?.dead && <Icon path={mdiCross} size={"1rem"} />}
|
|
|
|
</>
|
|
|
|
}
|
|
|
|
secondary={`${fmtDate(p.member?.dateOfBirth)} - ${fmtDate(
|
|
|
|
p.member?.dateOfDeath
|
|
|
|
)}`}
|
|
|
|
/>
|
|
|
|
{p.secondary && (
|
|
|
|
<ListItemSecondaryAction>{p.secondary}</ListItemSecondaryAction>
|
|
|
|
)}
|
|
|
|
</ListItemButton>
|
|
|
|
);
|
2023-08-10 12:13:27 +00:00
|
|
|
}
|