Skip to content

Instantly share code, notes, and snippets.

@13x54n
Created June 26, 2023 05:59
Show Gist options
  • Save 13x54n/06e169776461894d92a2a7c61ef5bce9 to your computer and use it in GitHub Desktop.
Save 13x54n/06e169776461894d92a2a7c61ef5bce9 to your computer and use it in GitHub Desktop.
Solution for the task given by Chameleon.
/*
@dev Improvements:
1. Made the component more generalized by passing menuItems, name and sync props.
menuItems is an array of objects with value and label.
Name is used for backend syncing. Sync determines if selection should be synced with backend.
2. Added state to track selected value and dropdown open state.
3. Added syncing with backend using httpPatch() on selection change,
and httpGet() on initial load if sync is true.
4. Allowed selecting an option by clicking its link.
*/
/*
@note For a PR review, I would suggest:
1. Adding prop types for type safety
2. Handling edge cases like no options passed
3. Allowing customization of class names
4. Adding comments for readability
*/
/*
@dev If I were to implement this from scratch, I would:
1. Use prop types
2. Pass default props
3. Add more customization options (styles, class names, etc.)
4. Improve accessibility
5. Add more complex functionality like search, multiple selection, etc.
*/
/*
@dev Release note:
Generalized dropdown component to accept options and enable backend syncing.
Can now be used for account selection, searchable lists, etc.
*/
import React from "react";
import { httpGet, httpPatch } from "./lib/http";
export const Dropdown = ({
label,
menuItems,
name,
defaultValue,
syncStatus,
}) => {
const [isOpen, setIsOpen] = React.useState(false);
const [selected, setSelected] = React.useState(
defaultValue || menuItems[0].value
);
React.useEffect(() => {
if (syncStatus)
httpPatch(`users/${userId}`, { [`menu-state-${name}`]: selected });
}, [selected, syncStatus]);
React.useEffect(() => {
if (syncStatus)
httpGet(`users/${userId}`).then((d) => {
setSelected(d[`menu-state-${name}`]);
});
}, [syncStatus]);
const onSelect = (value) => {
setSelected(value);
if (isOpen) setIsOpen(false);
};
const onToggleMenuItem = () => {
setIsOpen(!isOpen);
};
return (
<div className="dropdown">
<button
type="button"
className="dropdown-button"
id="dropdownButton"
aria-haspopup="true"
aria-expanded={isOpen}
onClick={() => onToggleMenuItem()}
>
{label} {selected}
</button>
<ul
className={`${isOpen ? "dropdown-open" : ""} dropdown-menu`}
aria-labelledby="dropdownButton"
>
{menuItems.map((item) => (
<li key={item.value}>
<a href="#" onClick={() => onSelect(item.value)}>
{item.label}
</a>
</li>
))}
</ul>
</div>
);
};
window.currentUser = { id: "19", name: "Jane", email: "jane@chameleon.io" };
export const ActiveProfiles = ({ profiles, onLaunchProfile }) => {
const active = [];
for (let i = 0; i < profiles.length; i++) {
if (
!profiles[i].disabled &&
profiles[i]["last_seen_time"] >
new Date(new Date().getTime() - 24 * 60 * 1000).toISOString()
) {
active.push(profiles[i]);
}
}
if (active.length === 1 && active[0].email === window.currentUser.email) {
active.length = 0;
}
return (
<div>
{active.map((a) => (
<div onClick={() => onLaunchProfile(a.name, a.email)}>
{a.name} - {a.email}
</div>
))}
</div>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment