Contacts: redesign the address book view and add filtering by group.
This is the first step towards fixing #136.master
parent
78e91abcb4
commit
55cae0962d
@ -0,0 +1,66 @@
|
||||
import * as React from "react";
|
||||
|
||||
import InboxIcon from "@material-ui/icons/Inbox";
|
||||
import LabelIcon from "@material-ui/icons/LabelOutlined";
|
||||
|
||||
import { List, ListItem, ListSubheader } from "../widgets/List";
|
||||
import { ContactType } from "../pim-types";
|
||||
|
||||
interface ListItemPropsType {
|
||||
name: string | undefined;
|
||||
icon?: React.ReactElement;
|
||||
primaryText: string;
|
||||
filterByGroup: string | undefined;
|
||||
setFilterByGroup: (group: string | undefined) => void;
|
||||
}
|
||||
|
||||
function SidebarListItem(props: ListItemPropsType) {
|
||||
const { name, icon, primaryText, filterByGroup } = props;
|
||||
|
||||
const handleClick = () => props.setFilterByGroup(name);
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
onClick={handleClick}
|
||||
selected={name === filterByGroup}
|
||||
leftIcon={icon}
|
||||
primaryText={primaryText}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
interface PropsType {
|
||||
groups: ContactType[];
|
||||
filterByGroup: string | undefined;
|
||||
setFilterByGroup: (group: string | undefined) => void;
|
||||
}
|
||||
|
||||
export default React.memo(function Sidebar(props: PropsType) {
|
||||
const { groups, filterByGroup, setFilterByGroup } = props;
|
||||
|
||||
const groupList = [...groups].sort((a, b) => a.fn.localeCompare(b.fn)).map((group) => (
|
||||
<SidebarListItem
|
||||
key={group.uid}
|
||||
name={group.uid}
|
||||
primaryText={group.fn}
|
||||
icon={<LabelIcon />}
|
||||
filterByGroup={filterByGroup}
|
||||
setFilterByGroup={setFilterByGroup}
|
||||
/>
|
||||
));
|
||||
|
||||
return (
|
||||
<List dense>
|
||||
<SidebarListItem
|
||||
name={undefined}
|
||||
primaryText="All"
|
||||
icon={<InboxIcon />}
|
||||
filterByGroup={filterByGroup}
|
||||
setFilterByGroup={setFilterByGroup}
|
||||
/>
|
||||
|
||||
<ListSubheader>Groups</ListSubheader>
|
||||
{groupList}
|
||||
</List>
|
||||
);
|
||||
});
|
@ -0,0 +1,64 @@
|
||||
import * as React from "react";
|
||||
|
||||
import SearchIcon from "@material-ui/icons/Search";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import { Transition } from "react-transition-group";
|
||||
import InputAdornment from "@material-ui/core/InputAdornment";
|
||||
|
||||
const transitionTimeout = 300;
|
||||
|
||||
const transitionStyles = {
|
||||
entering: { visibility: "visible", width: "100%", overflow: "hidden" },
|
||||
entered: { visibility: "visible", width: "100%" },
|
||||
exiting: { visibility: "visible", width: "0%", overflow: "hidden" },
|
||||
exited: { visibility: "hidden", width: "0%" },
|
||||
};
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
button: {
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
textField: {
|
||||
transition: `width ${transitionTimeout}ms`,
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
}));
|
||||
|
||||
interface PropsType {
|
||||
searchTerm: string;
|
||||
setSearchTerm: (term: string) => void;
|
||||
}
|
||||
|
||||
export default function Toolbar(props: PropsType) {
|
||||
const { searchTerm, setSearchTerm } = props;
|
||||
|
||||
const showSearchField = true;
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", justifyContent: "flex-end", alignItems: "center" }}>
|
||||
<Transition in={showSearchField} timeout={transitionTimeout}>
|
||||
{(state) => (
|
||||
<TextField
|
||||
fullWidth
|
||||
placeholder="Search"
|
||||
value={searchTerm}
|
||||
color="secondary"
|
||||
variant="standard"
|
||||
className={classes.textField}
|
||||
style={transitionStyles[state]}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<SearchIcon />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Transition>
|
||||
</div>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue