fix: Adjust Appearance of drawer

This commit is contained in:
Takeshi Kimata
2024-06-08 20:31:43 +09:00
parent 121fa7de55
commit 67d4c19686
8 changed files with 192 additions and 76 deletions

View File

@@ -0,0 +1,20 @@
import { User } from 'lucide-react';
import Avatar from 'boring-avatars';
import { TokenContextType } from '@/types/user';
type Props = {
context: TokenContextType;
};
export default function PublicityChip({ context }: Props) {
return context.isSignedIn() ? (
<Avatar
size={16}
name={context.token.user.username}
variant="beam"
colors={['#0A0310', '#49007E', '#FF005B', '#FF7D10', '#FFB238']}
/>
) : (
<User size={16} />
);
}

View File

@@ -1,8 +1,14 @@
const roles = [{ uid: 'administrator' }, { uid: 'user' }]; const roles = [{ uid: 'administrator' }, { uid: 'user' }];
const memberRoles = [{ uid: 'manager' }, { uid: 'developer' }, { uid: 'reporter' }]; const memberRoles = [{ uid: 'manager' }, { uid: 'developer' }, { uid: 'reporter' }];
const categoricalPalette = ['#fba91e', '#6ea56c', '#3ac6e1', '#feda2f', '#f15f47', '#244470', '#9c80bb', '#f595a6']; const categoricalPalette = ['#fba91e', '#6ea56c', '#3ac6e1', '#feda2f', '#f15f47', '#244470', '#9c80bb', '#f595a6'];
const locales = [
{ code: 'en', name: 'English' },
{ code: 'ja', name: '日本語' },
];
const priorities = [ const priorities = [
{ uid: 'critical', color: '#bb3e03', chartColor: '#bb3e03' }, { uid: 'critical', color: '#bb3e03', chartColor: '#bb3e03' },
{ uid: 'high', color: '#ca6702', chartColor: '#ca6702' }, { uid: 'high', color: '#ca6702', chartColor: '#ca6702' },
@@ -56,4 +62,14 @@ const testRunCaseStatus = [
{ uid: 'skipped', color: 'primary', chartColor: '#805aab' }, { uid: 'skipped', color: 'primary', chartColor: '#805aab' },
]; ];
export { roles, memberRoles, priorities, testTypes, automationStatus, templates, testRunStatus, testRunCaseStatus }; export {
roles,
memberRoles,
locales,
priorities,
testTypes,
automationStatus,
templates,
testRunStatus,
testRunCaseStatus,
};

View File

@@ -27,7 +27,9 @@
"account": "Account", "account": "Account",
"signup": "Sign up", "signup": "Sign up",
"signin": "Sign in", "signin": "Sign in",
"signout": "Sign out" "signout": "Sign out",
"links": "Links",
"languages": "Languages"
}, },
"Toast": { "Toast": {
"need_signed_in": "You need signed in", "need_signed_in": "You need signed in",

View File

@@ -27,7 +27,9 @@
"account": "アカウント", "account": "アカウント",
"signup": "新規登録", "signup": "新規登録",
"signin": "サインイン", "signin": "サインイン",
"signout": "サインアウト" "signout": "サインアウト",
"links": "リンク",
"languages": "言語"
}, },
"Toast": { "Toast": {
"need_signed_in": "サインインが必要です", "need_signed_in": "サインインが必要です",

View File

@@ -1,11 +1,11 @@
'use client'; 'use client';
import { Button, DropdownTrigger, Dropdown, DropdownMenu, DropdownItem } from '@nextui-org/react'; import { Button, DropdownTrigger, Dropdown, DropdownMenu, DropdownItem } from '@nextui-org/react';
import { User, ChevronDown, PenTool, ArrowRightFromLine, ArrowRightToLine } from 'lucide-react'; import { ChevronDown, PenTool, ArrowRightFromLine, ArrowRightToLine } from 'lucide-react';
import { useContext } from 'react'; import { useContext } from 'react';
import { TokenContext } from '@/utils/TokenProvider'; import { TokenContext } from '@/utils/TokenProvider';
import { useRouter } from '@/src/navigation'; import { useRouter } from '@/src/navigation';
import { AccountDropDownMessages } from '@/types/user'; import { AccountDropDownMessages } from '@/types/user';
import Avatar from 'boring-avatars'; import UserAvatar from '@/components/UserAvatar';
type Props = { type Props = {
messages: AccountDropDownMessages; messages: AccountDropDownMessages;
@@ -23,22 +23,11 @@ export default function DropdownAccount({ messages, locale, onItemPress }: Props
router.push(`/`, { locale: locale }); router.push(`/`, { locale: locale });
}; };
let userAvatar = context.isSignedIn() ? (
<Avatar
size={16}
name={context.token.user.username}
variant="beam"
colors={['#0A0310', '#49007E', '#FF005B', '#FF7D10', '#FFB238']}
/>
) : (
<User size={16} />
);
const signinItems = [ const signinItems = [
{ {
uid: 'account', uid: 'account',
title: messages.account, title: messages.account,
icon: userAvatar, icon: <UserAvatar context={context} />,
onPress: () => { onPress: () => {
router.push('/account', { locale: locale }); router.push('/account', { locale: locale });
onItemPress(); onItemPress();
@@ -79,7 +68,12 @@ export default function DropdownAccount({ messages, locale, onItemPress }: Props
return ( return (
<Dropdown> <Dropdown>
<DropdownTrigger> <DropdownTrigger>
<Button size="sm" variant="light" startContent={userAvatar} endContent={<ChevronDown size={16} />}> <Button
size="sm"
variant="light"
startContent={<UserAvatar context={context} />}
endContent={<ChevronDown size={16} />}
>
{context.isSignedIn() ? context.token.user.username : messages.signIn} {context.isSignedIn() ? context.token.user.username : messages.signIn}
</Button> </Button>
</DropdownTrigger> </DropdownTrigger>

View File

@@ -1,40 +1,24 @@
'use client'; 'use client';
import { Button, DropdownTrigger, Dropdown, DropdownMenu, DropdownItem } from '@nextui-org/react'; import { Button, DropdownTrigger, Dropdown, DropdownMenu, DropdownItem } from '@nextui-org/react';
import { Globe, ChevronDown } from 'lucide-react'; import { Globe, ChevronDown } from 'lucide-react';
import { usePathname } from 'next/navigation'; import { locales } from '@/config/selection';
import { useRouter } from '@/src/navigation';
const locales = [ type Props = {
{ code: 'en', name: 'English' }, locale: string;
{ code: 'ja', name: '日本語' }, onChangeLocale: (code: string) => void;
]; };
export default function DropdownLanguage(params: { locale: string }) {
const router = useRouter();
const pathname = usePathname();
async function changeLocale(nextLocale: string) {
let newPathname;
if (pathname.length < 4) {
// when root path
router.push('/', { locale: nextLocale });
} else {
// when not root path, trim first "/en" from pathname = "/en/projects"
newPathname = pathname.slice(params.locale.length + 1);
router.push(newPathname, { locale: nextLocale });
}
}
export default function DropdownLanguage({ locale, onChangeLocale }: Props) {
return ( return (
<Dropdown> <Dropdown>
<DropdownTrigger> <DropdownTrigger>
<Button size="sm" variant="light" startContent={<Globe size={16} />} endContent={<ChevronDown size={16} />}> <Button size="sm" variant="light" startContent={<Globe size={16} />} endContent={<ChevronDown size={16} />}>
{locales.find((locale) => locale.code === params.locale)?.name || params.locale} {locales.find((entry) => entry.code === locale)?.name || locale}
</Button> </Button>
</DropdownTrigger> </DropdownTrigger>
<DropdownMenu aria-label="lacales"> <DropdownMenu aria-label="lacales">
{locales.map((entry) => ( {locales.map((entry) => (
<DropdownItem key={entry.code} onClick={() => changeLocale(entry.code)}> <DropdownItem key={entry.code} onClick={() => onChangeLocale(entry.code)}>
{entry.name} {entry.name}
</DropdownItem> </DropdownItem>
))} ))}

View File

@@ -11,6 +11,8 @@ export default function Header(params: { locale: string }) {
signUp: t('signup'), signUp: t('signup'),
signIn: t('signin'), signIn: t('signin'),
signOut: t('signout'), signOut: t('signout'),
links: t('links'),
languages: t('languages'),
}; };
return <HeaderNavbarMenu messages={messages} locale={params.locale} />; return <HeaderNavbarMenu messages={messages} locale={params.locale} />;

View File

@@ -1,7 +1,8 @@
'use client'; 'use client';
import { useState, useContext } from 'react'; import { useState, useContext } from 'react';
import { TokenContext } from '@/utils/TokenProvider'; import { TokenContext } from '@/utils/TokenProvider';
import { Link } from '@/src/navigation'; import { Link, useRouter } from '@/src/navigation';
import { usePathname } from 'next/navigation';
import Image from 'next/image'; import Image from 'next/image';
import { import {
Navbar, Navbar,
@@ -10,15 +11,18 @@ import {
NavbarMenuToggle, NavbarMenuToggle,
NavbarBrand, NavbarBrand,
NavbarItem, NavbarItem,
NavbarMenuItem,
Link as NextUiLink, Link as NextUiLink,
Chip, Chip,
ListboxItem,
Listbox,
} from '@nextui-org/react'; } from '@nextui-org/react';
import { MoveUpRight } from 'lucide-react'; import { ArrowRightFromLine, ArrowRightToLine, File, Globe, MoveUpRight, PenTool } from 'lucide-react';
import { ThemeSwitch } from '@/components/theme-switch'; import { ThemeSwitch } from '@/components/theme-switch';
import { GithubIcon } from '@/components/icons'; import { GithubIcon } from '@/components/icons';
import { locales } from '@/config/selection';
import DropdownAccount from './DropdownAccount'; import DropdownAccount from './DropdownAccount';
import DropdownLanguage from './DropdownLanguage'; import DropdownLanguage from './DropdownLanguage';
import UserAvatar from '@/components/UserAvatar';
type NabbarMenuMessages = { type NabbarMenuMessages = {
projects: string; projects: string;
@@ -28,6 +32,8 @@ type NabbarMenuMessages = {
signUp: string; signUp: string;
signIn: string; signIn: string;
signOut: string; signOut: string;
links: string;
languages: string;
}; };
type Props = { type Props = {
@@ -54,6 +60,20 @@ export default function HeaderNavbarMenu({ messages, locale }: Props) {
}, },
]; ];
const router = useRouter();
const pathname = usePathname();
async function changeLocale(nextLocale: string) {
let newPathname;
if (pathname.length < 4) {
// when root path
router.push('/', { locale: nextLocale });
} else {
// when not root path, trim first "/en" from pathname = "/en/projects"
newPathname = pathname.slice(locale.length + 1);
router.push(newPathname, { locale: nextLocale });
}
}
return ( return (
<Navbar isMenuOpen={isMenuOpen} maxWidth="full" position="sticky" className="bg-inherit"> <Navbar isMenuOpen={isMenuOpen} maxWidth="full" position="sticky" className="bg-inherit">
<NavbarContent className="basis-1/5 sm:basis-full" justify="start"> <NavbarContent className="basis-1/5 sm:basis-full" justify="start">
@@ -115,44 +135,120 @@ export default function HeaderNavbarMenu({ messages, locale }: Props) {
<ThemeSwitch /> <ThemeSwitch />
<div className="hidden md:block"> <div className="hidden md:block">
<DropdownAccount messages={messages} locale={locale} onItemPress={() => {}} /> <DropdownAccount messages={messages} locale={locale} onItemPress={() => {}} />
<DropdownLanguage locale={locale} /> <DropdownLanguage locale={locale} onChangeLocale={changeLocale} />
</div> </div>
<NavbarMenuToggle className="md:hidden" onClick={() => setIsMenuOpen(!isMenuOpen)} /> <NavbarMenuToggle className="md:hidden" onClick={() => setIsMenuOpen(!isMenuOpen)} />
</NavbarContent> </NavbarContent>
<NavbarMenu> <NavbarMenu>
<div className="mx-4 mt-2 flex flex-col gap-2"> <div className="mx-4 mt-2 flex flex-col gap-2">
<NavbarMenuItem> <p className="font-bold">{messages.links}</p>
<DropdownAccount messages={messages} locale={locale} onItemPress={() => setIsMenuOpen(false)} /> <Listbox
</NavbarMenuItem> aria-label="Links"
<NavbarMenuItem> itemClasses={{
<DropdownLanguage locale={locale} /> base: 'h-10 text-large',
</NavbarMenuItem> }}
>
{commonLinks.map((link) => {commonLinks.map((link) =>
link.isExternal ? ( link.isExternal ? (
<NavbarMenuItem key={link.uid}> <ListboxItem
<NextUiLink key={link.uid}
href={link.href} title={link.label}
onPress={() => setIsMenuOpen(false)} startContent={<MoveUpRight size={12} />}
showAnchorIcon onPress={() => {
anchorIcon={<MoveUpRight size={12} className="ms-1" />} router.push(link.href, { locale: locale });
> setIsMenuOpen(false);
{messages.docs} }}
</NextUiLink> />
</NavbarMenuItem>
) : ( ) : (
<NavbarMenuItem key={link.uid}> <ListboxItem
<Link key={link.uid}
className="data-[active=true]:text-primary data-[active=true]:font-medium" title={link.label}
href={link.href} startContent={<File size={12} />}
locale={locale} onPress={() => {
onClick={() => setIsMenuOpen(false)} router.push(link.href, { locale: locale });
> setIsMenuOpen(false);
{link.label} }}
</Link> />
</NavbarMenuItem>
) )
)} )}
</Listbox>
<p className="font-bold">{messages.account}</p>
{context.isSignedIn() ? (
<Listbox
aria-label="Account links"
itemClasses={{
base: 'h-10 text-large',
}}
>
<ListboxItem
key="account"
title={messages.account}
startContent={<UserAvatar context={context} />}
onPress={() => {
router.push('/account', { locale: locale });
setIsMenuOpen(false);
}}
/>
<ListboxItem
key="signout"
title={messages.signOut}
startContent={<ArrowRightFromLine size={16} />}
onPress={() => {
context.setToken(null);
context.removeTokenFromLocalStorage();
router.push(`/`, { locale: locale });
setIsMenuOpen(false);
}}
/>
</Listbox>
) : (
<Listbox
aria-label="Account links"
itemClasses={{
base: 'h-10 text-large',
}}
>
<ListboxItem
key="signin"
startContent={<ArrowRightToLine size={16} />}
title={messages.signIn}
onClick={() => {
router.push('/account/signin', { locale: locale });
setIsMenuOpen(false);
}}
/>
<ListboxItem
key="signup"
title={messages.signUp}
startContent={<PenTool size={16} />}
onClick={() => {
router.push('/account/signup', { locale: locale });
setIsMenuOpen(false);
}}
/>
</Listbox>
)}
<p className="font-bold">{messages.languages}</p>
<Listbox
aria-label="Language links"
itemClasses={{
base: 'h-10 text-large',
}}
>
{locales.map((entry) => (
<ListboxItem
key={entry.code}
startContent={<Globe size={16} />}
title={entry.name}
onClick={() => {
changeLocale(entry.code);
setIsMenuOpen(false);
}}
/>
))}
</Listbox>
</div> </div>
</NavbarMenu> </NavbarMenu>
</Navbar> </Navbar>