feat: mobile menu page instead of dropdown for authorized user

This commit is contained in:
Kentai Radiquum 2024-09-21 01:54:02 +05:00
parent 3ab5954197
commit 75eb4a3170
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
5 changed files with 327 additions and 180 deletions

View file

@ -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>
);
};

View 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>
);
};

9
app/menu/page.tsx Normal file
View file

@ -0,0 +1,9 @@
export const metadata = {
title: "Меню",
};
import { MenuPage } from "#/pages/MobileMenuPage";
export default function Index() {
return <MenuPage />;
}

View file

@ -0,0 +1,115 @@
"use client";
import { Card } from "flowbite-react";
import { useUserStore } from "#/store/auth";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { SettingsModal } from "#/components/SettingsModal/SettingsModal";
import { useEffect, useState } from "react";
export const MenuPage = () => {
const userStore = useUserStore();
const router = useRouter();
const [isSettingModalOpen, setIsSettingModalOpen] = useState(false);
useEffect(() => {
if (!userStore.user) {
router.push("/");
}
}, [userStore.user]);
return (
<>
{userStore.user && (
<div className="flex flex-col gap-2">
<div className="flex flex-wrap items-center gap-2">
<Link href={`/profile/${userStore.user.id}`} className="flex-1">
<Card>
<div className="flex items-center gap-4">
<img
src={userStore.user.avatar}
alt=""
className="w-16 h-16 rounded-full sm:w-28 sm:h-28"
/>
<div>
<p className="text-xl sm:text-2xl">
{userStore.user.login}
</p>
<p className="text-sm text-gray-400 whitespace-pre sm:text-base dark:text-gray-300">
{userStore.user.status}
</p>
</div>
</div>
</Card>
</Link>
<div className="flex flex-1 h-full gap-2 sm:flex-col">
<button
className="flex-1"
onClick={() => {
userStore.logout();
}}
>
<Card>
<div className="flex items-center justify-center gap-2 sm:justify-start">
<span
className={`iconify material-symbols--logout-rounded w-6 h-6 text-red-500`}
></span>
<p className="text-red-500">Выйти</p>
</div>
</Card>
</button>
<button
className="flex-1"
onClick={() => {
setIsSettingModalOpen(true);
}}
>
<Card className="flex-1">
<div className="flex items-center justify-center gap-2 sm:justify-start">
<span
className={`iconify material-symbols--settings-outline-rounded w-6 h-6`}
></span>
<p>Настройки</p>
</div>
</Card>
</button>
</div>
</div>
<Link href="/favorites" className="flex-1">
<Card>
<div className="flex items-center gap-2">
<span
className={`iconify material-symbols--favorite-outline w-6 h-6`}
></span>
<p>Избранное</p>
</div>
</Card>
</Link>
<Link href="/collections" className="flex-1">
<Card>
<div className="flex items-center gap-2">
<span
className={`iconify material-symbols--collections-bookmark-outline w-6 h-6`}
></span>
<p>Коллекции</p>
</div>
</Card>
</Link>
<Link href="/history" className="flex-1">
<Card>
<div className="flex items-center gap-2">
<span
className={`iconify material-symbols--history w-6 h-6`}
></span>
<p>История</p>
</div>
</Card>
</Link>
<SettingsModal
isOpen={isSettingModalOpen}
setIsOpen={setIsSettingModalOpen}
/>
</div>
)}
</>
);
};

View file

@ -3,10 +3,11 @@
## Добавлено
- Редактирование профиля
- Страница меню, для авторизованного пользователя, вместо выпадающего списка на мобильных устройствах
## Изменено
- Изменён вид каруселей
- Изменён вид каруселей релизов для ПК
## Исправлено