mirror of
https://github.com/aykhans/slash-e.git
synced 2025-07-25 06:14:25 +00:00
chore: add user detail page
This commit is contained in:
@@ -16,7 +16,9 @@ const Header: React.FC = () => {
|
||||
return (
|
||||
<div className="w-full bg-amber-50">
|
||||
<div className="w-full max-w-4xl mx-auto px-3 py-4 flex flex-row justify-between items-center">
|
||||
<span className="text-xl font-mono font-medium">Corgi</span>
|
||||
<span className="text-xl font-mono font-medium cursor-pointer" onClick={() => navigate("/")}>
|
||||
Corgi
|
||||
</span>
|
||||
<div className="relative">
|
||||
<Dropdown
|
||||
trigger={
|
||||
@@ -27,11 +29,21 @@ const Header: React.FC = () => {
|
||||
}
|
||||
actions={
|
||||
<>
|
||||
<span className="w-full px-2 leading-8 cursor-pointer rounded hover:bg-gray-100" onClick={() => handleSignOutButtonClick()}>
|
||||
<span
|
||||
className="w-full px-3 leading-8 cursor-pointer rounded whitespace-nowrap hover:bg-gray-100"
|
||||
onClick={() => navigate(`/user/${user?.id}`)}
|
||||
>
|
||||
My information
|
||||
</span>
|
||||
<span
|
||||
className="w-full px-3 leading-8 cursor-pointer rounded whitespace-nowrap hover:bg-gray-100"
|
||||
onClick={() => handleSignOutButtonClick()}
|
||||
>
|
||||
Sign out
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
actionsClassName="!w-36"
|
||||
></Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -45,6 +45,7 @@ const ShortcutListView: React.FC<Props> = (props: Props) => {
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
actionsClassName="!w-24"
|
||||
></Dropdown>
|
||||
</div>
|
||||
);
|
||||
|
@@ -49,6 +49,7 @@ const WorkspaceListView: React.FC<Props> = (props: Props) => {
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
actionsClassName="!w-24"
|
||||
></Dropdown>
|
||||
</div>
|
||||
);
|
||||
|
@@ -1,16 +1,16 @@
|
||||
import { ReactNode, useEffect, useRef } from "react";
|
||||
import useToggle from "../../hooks/useToggle";
|
||||
import Icon from "../Icon";
|
||||
import "../../less/common/dropdown.less";
|
||||
|
||||
interface Props {
|
||||
trigger?: ReactNode;
|
||||
actions?: ReactNode;
|
||||
className?: string;
|
||||
actionsClassName?: string;
|
||||
}
|
||||
|
||||
const Dropdown: React.FC<Props> = (props: Props) => {
|
||||
const { trigger, actions, className } = props;
|
||||
const { trigger, actions, className, actionsClassName } = props;
|
||||
const [dropdownStatus, toggleDropdownStatus] = useToggle(false);
|
||||
const dropdownWrapperRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@@ -29,15 +29,25 @@ const Dropdown: React.FC<Props> = (props: Props) => {
|
||||
}, [dropdownStatus]);
|
||||
|
||||
return (
|
||||
<div ref={dropdownWrapperRef} className={`dropdown-wrapper ${className ?? ""}`} onClick={() => toggleDropdownStatus()}>
|
||||
<div
|
||||
ref={dropdownWrapperRef}
|
||||
className={`relative flex flex-col justify-start items-start select-none ${className ?? ""}`}
|
||||
onClick={() => toggleDropdownStatus()}
|
||||
>
|
||||
{trigger ? (
|
||||
trigger
|
||||
) : (
|
||||
<span className="trigger-button">
|
||||
<Icon.MoreHorizontal className="icon-img" />
|
||||
<span className="flex flex-row justify-center items-center border p-1 rounded shadow text-gray-600 cursor-pointer hover:opacity-80">
|
||||
<Icon.MoreHorizontal className="w-4 h-auto" />
|
||||
</span>
|
||||
)}
|
||||
<div className={`action-buttons-container ${dropdownStatus ? "" : "!hidden"}`}>{actions}</div>
|
||||
<div
|
||||
className={`w-auto mt-1 absolute top-full right-0 flex flex-col justify-start items-start bg-white z-1 border p-1 rounded-md shadow ${
|
||||
actionsClassName ?? ""
|
||||
} ${dropdownStatus ? "" : "!hidden"}`}
|
||||
>
|
||||
{actions}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@@ -1,95 +0,0 @@
|
||||
import { memo, useEffect, useRef } from "react";
|
||||
import useToggle from "../../hooks/useToggle";
|
||||
import Icon from "../Icon";
|
||||
import "../../less/common/selector.less";
|
||||
|
||||
interface SelectorItem {
|
||||
text: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
value: string;
|
||||
dataSource: SelectorItem[];
|
||||
handleValueChanged?: (value: string) => void;
|
||||
}
|
||||
|
||||
const nullItem = {
|
||||
text: "Select",
|
||||
value: "",
|
||||
};
|
||||
|
||||
const Selector: React.FC<Props> = (props: Props) => {
|
||||
const { className, dataSource, handleValueChanged, value } = props;
|
||||
const [showSelector, toggleSelectorStatus] = useToggle(false);
|
||||
|
||||
const seletorElRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
let currentItem = nullItem;
|
||||
for (const d of dataSource) {
|
||||
if (d.value === value) {
|
||||
currentItem = d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (showSelector) {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (!seletorElRef.current?.contains(event.target as Node)) {
|
||||
toggleSelectorStatus(false);
|
||||
}
|
||||
};
|
||||
window.addEventListener("click", handleClickOutside, {
|
||||
capture: true,
|
||||
once: true,
|
||||
});
|
||||
}
|
||||
}, [showSelector]);
|
||||
|
||||
const handleItemClick = (item: SelectorItem) => {
|
||||
if (handleValueChanged) {
|
||||
handleValueChanged(item.value);
|
||||
}
|
||||
toggleSelectorStatus(false);
|
||||
};
|
||||
|
||||
const handleCurrentValueClick = (event: React.MouseEvent) => {
|
||||
event.stopPropagation();
|
||||
toggleSelectorStatus();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`selector-wrapper ${className ?? ""}`} ref={seletorElRef}>
|
||||
<div className={`current-value-container ${showSelector ? "active" : ""}`} onClick={handleCurrentValueClick}>
|
||||
<span className="value-text">{currentItem.text}</span>
|
||||
<span className="arrow-text">
|
||||
<Icon.ChevronDown className="icon-img" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className={`items-wrapper ${showSelector ? "" : "!hidden"}`}>
|
||||
{dataSource.length > 0 ? (
|
||||
dataSource.map((d) => {
|
||||
return (
|
||||
<div
|
||||
className={`item-container ${d.value === value ? "selected" : ""}`}
|
||||
key={d.value}
|
||||
onClick={() => {
|
||||
handleItemClick(d);
|
||||
}}
|
||||
>
|
||||
{d.text}
|
||||
</div>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<p className="tip-text">Null</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(Selector);
|
Reference in New Issue
Block a user