Add foundational components and logic for migration, UI design, and input handling
- Introduced foundational UI components (`Badge`, `LockCard`, `SectionHeader`, `AvatarIcon`, etc.) for flexible layouts and consistent design. - Added migration support with the `MigrationModal` component and backend integration for exporting/importing data between Electron and Tauri. - Extended form components with `TextAreaInput`, `OrderInput`, `ToggleField`, and `ToolbarSelect` for improved input handling. - Updated `ScribeShell` with migration popup logic to prompt users for data migration. - Integrated `AlertStack` for better alert handling and notification management. - Enhanced Rust/Tauri services with migration command implementations. - Added translations and styles for new components.
This commit is contained in:
84
components/layout/UserMenu.tsx
Normal file
84
components/layout/UserMenu.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import React, {useContext, useEffect, useRef, useState} from "react";
|
||||
import {SessionContext, SessionContextProps} from "@/context/SessionContext";
|
||||
import AvatarIcon from "@/components/ui/AvatarIcon";
|
||||
import {removeCookie} from '@/lib/utils/cookies';
|
||||
import {isDesktop} from '@/lib/configs';
|
||||
import * as tauri from '@/lib/tauri';
|
||||
import {useTranslations} from '@/lib/i18n';
|
||||
|
||||
export default function UserMenu(): React.JSX.Element {
|
||||
const {session}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
|
||||
const t = useTranslations();
|
||||
|
||||
const profileMenuRef: React.RefObject<HTMLDivElement | null> = useRef<HTMLDivElement>(null);
|
||||
|
||||
const [isProfileMenuOpen, setIsProfileMenuOpen] = useState<boolean>(false);
|
||||
|
||||
function handleProfileClick(): void {
|
||||
setIsProfileMenuOpen(!isProfileMenuOpen);
|
||||
}
|
||||
|
||||
useEffect((): () => void => {
|
||||
function handleClickOutside(event: MouseEvent): void {
|
||||
if (profileMenuRef.current && event.target instanceof Node && !profileMenuRef.current.contains(event.target)) {
|
||||
setIsProfileMenuOpen(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (isProfileMenuOpen) {
|
||||
document.addEventListener("mousedown", handleClickOutside);
|
||||
}
|
||||
|
||||
return (): void => {
|
||||
document.removeEventListener("mousedown", handleClickOutside);
|
||||
};
|
||||
}, [isProfileMenuOpen]);
|
||||
|
||||
function handleLogout(): void {
|
||||
removeCookie("token");
|
||||
if (isDesktop) {
|
||||
tauri.logout();
|
||||
} else {
|
||||
document.location.href = "https://eritors.com/login";
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative" data-guide="user-dropdown" ref={profileMenuRef}>
|
||||
<button
|
||||
className="bg-secondary hover:bg-gray-dark p-1.5 rounded-full transition-colors duration-150 flex items-center border border-secondary hover:border-primary"
|
||||
onClick={session.user ? handleProfileClick : (): void => {
|
||||
document.location.href = "/login";
|
||||
}}
|
||||
>
|
||||
{
|
||||
session.user && (
|
||||
<AvatarIcon
|
||||
size="xs"
|
||||
initial={session.user.username?.charAt(0).toUpperCase() ?? ''}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</button>
|
||||
{isProfileMenuOpen && (
|
||||
<div
|
||||
className="absolute right-0 mt-3 w-56 bg-tertiary rounded-xl py-2 z-[100] border border-secondary backdrop-blur-sm animate-fadeIn">
|
||||
<div
|
||||
className="px-4 py-3 border-b border-secondary bg-gradient-to-r from-primary/10 to-transparent">
|
||||
<p className="text-text-primary font-bold text-sm tracking-wide">{session.user?.username}</p>
|
||||
<p className="text-text-secondary text-xs mt-0.5">{session.user?.email}</p>
|
||||
</div>
|
||||
<a href="https://eritors.com/settings"
|
||||
className="group flex items-center gap-3 px-4 py-2.5 text-text-primary hover:bg-secondary transition-all hover:pl-5">
|
||||
<span
|
||||
className="text-sm font-medium group-hover:text-primary transition-colors">{t("userMenu.settings")}</span>
|
||||
</a>
|
||||
<a onClick={handleLogout} href="#"
|
||||
className="group flex items-center gap-3 px-4 py-2.5 text-error hover:bg-error/10 transition-all hover:pl-5 rounded-b-xl">
|
||||
<span className="text-sm font-medium">{t("userMenu.logout")}</span>
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user