mirror of
https://github.com/Radiquum/AniX.git
synced 2025-04-28 00:49:40 +05:00
feat: mobile menu page instead of dropdown for authorized user
This commit is contained in:
parent
3ab5954197
commit
75eb4a3170
5 changed files with 327 additions and 180 deletions
|
@ -2,16 +2,10 @@
|
|||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useUserStore } from "#/store/auth";
|
||||
import { usePreferencesStore } from "#/store/preferences";
|
||||
import {
|
||||
Dropdown,
|
||||
Modal,
|
||||
Button,
|
||||
useThemeMode,
|
||||
ToggleSwitch,
|
||||
} from "flowbite-react";
|
||||
import { Dropdown } from "flowbite-react";
|
||||
import { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { SettingsModal } from "#/components/SettingsModal/SettingsModal";
|
||||
|
||||
export const Navbar = () => {
|
||||
const pathname = usePathname();
|
||||
|
@ -110,93 +104,114 @@ export const Navbar = () => {
|
|||
})}
|
||||
</nav>
|
||||
{userStore.isAuth ? (
|
||||
<div className="flex flex-col items-center justify-end text-sm lg:gap-1 lg:justify-center lg:flex-row lg:text-base">
|
||||
<Image
|
||||
src={userStore.user.avatar}
|
||||
alt=""
|
||||
className="w-6 h-6 rounded-full"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
<Dropdown
|
||||
label={userStore.user.login}
|
||||
inline={true}
|
||||
dismissOnClick={true}
|
||||
theme={{
|
||||
arrowIcon:
|
||||
"ml-1 w-4 h-4 [transform:rotateX(180deg)] sm:transform-none",
|
||||
floating: {
|
||||
target: "text-sm sm:text-base",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Dropdown.Item className="text-sm md:text-base">
|
||||
<Link
|
||||
href={`/profile/${userStore.user.id}`}
|
||||
className="flex items-center gap-1"
|
||||
<>
|
||||
<div className="flex-col items-center justify-end hidden text-sm md:flex lg:gap-1 lg:justify-center lg:flex-row lg:text-base">
|
||||
<Image
|
||||
src={userStore.user.avatar}
|
||||
alt=""
|
||||
className="w-6 h-6 rounded-full"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
<Dropdown
|
||||
label={userStore.user.login}
|
||||
inline={true}
|
||||
dismissOnClick={true}
|
||||
theme={{
|
||||
arrowIcon:
|
||||
"ml-1 w-4 h-4 [transform:rotateX(180deg)] sm:transform-none",
|
||||
floating: {
|
||||
target: "text-sm sm:text-base",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Dropdown.Item className="text-sm md:text-base">
|
||||
<Link
|
||||
href={`/profile/${userStore.user.id}`}
|
||||
className="flex items-center gap-1"
|
||||
>
|
||||
<span
|
||||
className={`iconify ${
|
||||
pathname == `/profile/${userStore.user.id}`
|
||||
? "font-bold mdi--user"
|
||||
: "mdi--user-outline"
|
||||
} w-6 h-6`}
|
||||
></span>
|
||||
<span>Профиль</span>
|
||||
</Link>
|
||||
</Dropdown.Item>
|
||||
{navLinks.map((link) => {
|
||||
return (
|
||||
<Dropdown.Item
|
||||
key={link.id + "_mobile"}
|
||||
className={`${
|
||||
link.mobileMenu ? "block sm:hidden" : "hidden"
|
||||
} text-sm md:text-base`}
|
||||
>
|
||||
<Link
|
||||
href={link.href}
|
||||
className={`flex items-center gap-1`}
|
||||
>
|
||||
<span
|
||||
className={`iconify ${
|
||||
pathname == link.href
|
||||
? link.iconActive
|
||||
: link.icon
|
||||
} w-6 h-6`}
|
||||
></span>
|
||||
<span
|
||||
className={`${
|
||||
pathname == link.href ? "font-bold" : ""
|
||||
}`}
|
||||
>
|
||||
{link.title}
|
||||
</span>
|
||||
</Link>
|
||||
</Dropdown.Item>
|
||||
);
|
||||
})}
|
||||
<Dropdown.Item
|
||||
onClick={() => {
|
||||
setIsSettingModalOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-1 text-sm md:text-base"
|
||||
>
|
||||
<span
|
||||
className={`iconify ${
|
||||
pathname == `/profile/${userStore.user.id}`
|
||||
? "font-bold mdi--user"
|
||||
: "mdi--user-outline"
|
||||
} w-6 h-6`}
|
||||
className={`iconify material-symbols--settings-outline-rounded w-6 h-6`}
|
||||
></span>
|
||||
<span>Профиль</span>
|
||||
</Link>
|
||||
</Dropdown.Item>
|
||||
{navLinks.map((link) => {
|
||||
return (
|
||||
<Dropdown.Item
|
||||
key={link.id + "_mobile"}
|
||||
className={`${
|
||||
link.mobileMenu ? "block sm:hidden" : "hidden"
|
||||
} text-sm md:text-base`}
|
||||
>
|
||||
<Link
|
||||
href={link.href}
|
||||
className={`flex items-center gap-1`}
|
||||
>
|
||||
<span
|
||||
className={`iconify ${
|
||||
pathname == link.href ? link.iconActive : link.icon
|
||||
} w-6 h-6`}
|
||||
></span>
|
||||
<span
|
||||
className={`${
|
||||
pathname == link.href ? "font-bold" : ""
|
||||
}`}
|
||||
>
|
||||
{link.title}
|
||||
</span>
|
||||
</Link>
|
||||
</Dropdown.Item>
|
||||
);
|
||||
})}
|
||||
<Dropdown.Item
|
||||
onClick={() => {
|
||||
setIsSettingModalOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-1 text-sm md:text-base"
|
||||
<span>Настройки</span>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
onClick={() => {
|
||||
userStore.logout();
|
||||
}}
|
||||
className="flex items-center gap-1 text-sm md:text-base"
|
||||
>
|
||||
<span
|
||||
className={`iconify material-symbols--logout-rounded w-6 h-6`}
|
||||
></span>
|
||||
<span>Выйти</span>
|
||||
</Dropdown.Item>
|
||||
</Dropdown>
|
||||
</div>
|
||||
<div className="block md:hidden">
|
||||
<Link
|
||||
href={"/menu"}
|
||||
className={`flex flex-col items-center justify-end text-sm md:hidden lg:gap-1 lg:justify-center lg:flex-row lg:text-base ${
|
||||
pathname == "/menu" ? "font-bold" : ""
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`iconify material-symbols--settings-outline-rounded w-6 h-6`}
|
||||
></span>
|
||||
<span>Настройки</span>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
onClick={() => {
|
||||
userStore.logout();
|
||||
}}
|
||||
className="flex items-center gap-1 text-sm md:text-base"
|
||||
>
|
||||
<span
|
||||
className={`iconify material-symbols--logout-rounded w-6 h-6`}
|
||||
></span>
|
||||
<span>Выйти</span>
|
||||
</Dropdown.Item>
|
||||
</Dropdown>
|
||||
</div>
|
||||
<Image
|
||||
src={userStore.user.avatar}
|
||||
alt=""
|
||||
className="w-6 h-6 rounded-full"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
<p>{userStore.user.login}</p>
|
||||
</Link>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<Dropdown
|
||||
label=""
|
||||
|
@ -258,91 +273,3 @@ export const Navbar = () => {
|
|||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
|
||||
const preferenceStore = usePreferencesStore();
|
||||
|
||||
const { computedMode, setMode } = useThemeMode();
|
||||
|
||||
return (
|
||||
<Modal
|
||||
dismissible
|
||||
show={props.isOpen}
|
||||
onClose={() => props.setIsOpen(false)}
|
||||
>
|
||||
<Modal.Header>Настройки</Modal.Header>
|
||||
<Modal.Body>
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="font-bold dark:text-white">Тема</p>
|
||||
<Button.Group>
|
||||
<Button
|
||||
color={computedMode == "light" ? "blue" : "gray"}
|
||||
onClick={() => setMode("light")}
|
||||
>
|
||||
Светлая
|
||||
</Button>
|
||||
<Button
|
||||
color={computedMode == "dark" ? "blue" : "gray"}
|
||||
onClick={() => setMode("dark")}
|
||||
>
|
||||
Темная
|
||||
</Button>
|
||||
</Button.Group>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="font-bold dark:text-white">
|
||||
Показывать список изменений
|
||||
</p>
|
||||
<ToggleSwitch
|
||||
color="blue"
|
||||
theme={{
|
||||
toggle: {
|
||||
checked: {
|
||||
color: {
|
||||
blue: "border-blue-700 bg-blue-700",
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
onChange={() =>
|
||||
preferenceStore.setFlags({
|
||||
showChangelog: !preferenceStore.flags.showChangelog,
|
||||
})
|
||||
}
|
||||
checked={preferenceStore.flags.showChangelog}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="font-bold dark:text-white">
|
||||
Отправка аналитики
|
||||
</p>
|
||||
<p className="text-gray-500 dark:text-gray-400">
|
||||
Требуется перезагрузка для применения
|
||||
</p>
|
||||
</div>
|
||||
<ToggleSwitch
|
||||
color="blue"
|
||||
theme={{
|
||||
toggle: {
|
||||
checked: {
|
||||
color: {
|
||||
blue: "border-blue-700 bg-blue-700",
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
onChange={() =>
|
||||
preferenceStore.setFlags({
|
||||
enableAnalytics: !preferenceStore.flags.enableAnalytics,
|
||||
})
|
||||
}
|
||||
checked={preferenceStore.flags.enableAnalytics}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
|
95
app/components/SettingsModal/SettingsModal.tsx
Normal file
95
app/components/SettingsModal/SettingsModal.tsx
Normal file
|
@ -0,0 +1,95 @@
|
|||
"use client";
|
||||
|
||||
import { usePreferencesStore } from "#/store/preferences";
|
||||
import {
|
||||
Modal,
|
||||
Button,
|
||||
useThemeMode,
|
||||
ToggleSwitch,
|
||||
} from "flowbite-react";
|
||||
|
||||
export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
|
||||
const preferenceStore = usePreferencesStore();
|
||||
|
||||
const { computedMode, setMode } = useThemeMode();
|
||||
|
||||
return (
|
||||
<Modal
|
||||
dismissible
|
||||
show={props.isOpen}
|
||||
onClose={() => props.setIsOpen(false)}
|
||||
>
|
||||
<Modal.Header>Настройки</Modal.Header>
|
||||
<Modal.Body>
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="font-bold dark:text-white">Тема</p>
|
||||
<Button.Group>
|
||||
<Button
|
||||
color={computedMode == "light" ? "blue" : "gray"}
|
||||
onClick={() => setMode("light")}
|
||||
>
|
||||
Светлая
|
||||
</Button>
|
||||
<Button
|
||||
color={computedMode == "dark" ? "blue" : "gray"}
|
||||
onClick={() => setMode("dark")}
|
||||
>
|
||||
Темная
|
||||
</Button>
|
||||
</Button.Group>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="font-bold dark:text-white">
|
||||
Показывать список изменений
|
||||
</p>
|
||||
<ToggleSwitch
|
||||
color="blue"
|
||||
theme={{
|
||||
toggle: {
|
||||
checked: {
|
||||
color: {
|
||||
blue: "border-blue-700 bg-blue-700",
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
onChange={() =>
|
||||
preferenceStore.setFlags({
|
||||
showChangelog: !preferenceStore.flags.showChangelog,
|
||||
})
|
||||
}
|
||||
checked={preferenceStore.flags.showChangelog}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="font-bold dark:text-white">Отправка аналитики</p>
|
||||
<p className="text-gray-500 dark:text-gray-400">
|
||||
Требуется перезагрузка для применения
|
||||
</p>
|
||||
</div>
|
||||
<ToggleSwitch
|
||||
color="blue"
|
||||
theme={{
|
||||
toggle: {
|
||||
checked: {
|
||||
color: {
|
||||
blue: "border-blue-700 bg-blue-700",
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
onChange={() =>
|
||||
preferenceStore.setFlags({
|
||||
enableAnalytics: !preferenceStore.flags.enableAnalytics,
|
||||
})
|
||||
}
|
||||
checked={preferenceStore.flags.enableAnalytics}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
);
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue