Добавлен новый компонент TabsNav для управления навигацией по вкладкам в страницах аккаунта и статистики. Обновлены соответствующие страницы для использования нового компонента, что улучшает структуру кода и упрощает управление вкладками. Также внесены изменения в стили для улучшения визуального восприятия.

This commit is contained in:
Redsandyg 2025-06-07 17:17:20 +03:00
parent 14921074a5
commit 5614894e49
10 changed files with 204 additions and 96 deletions

View File

@ -23,6 +23,7 @@ import AccountProfile from "../../components/AccountProfile";
import AccountSecurity from "../../components/AccountSecurity"; import AccountSecurity from "../../components/AccountSecurity";
import AccountNotifications from "../../components/AccountNotifications"; import AccountNotifications from "../../components/AccountNotifications";
import AccountAgentTransactionSection from "../../components/AccountAgentTransactionSection"; import AccountAgentTransactionSection from "../../components/AccountAgentTransactionSection";
import TabsNav from "../../components/TabsNav";
const initialNotifications = { const initialNotifications = {
emailNotifications: true, emailNotifications: true,
@ -54,22 +55,7 @@ export default function AccountPage() {
<div className={styles.dashboard}> <div className={styles.dashboard}>
<h1 className={styles.title}>Аккаунт</h1> <h1 className={styles.title}>Аккаунт</h1>
<div className={accountStyles.accountTabsNav}> <div className={accountStyles.accountTabsNav}>
<nav className={accountStyles.accountTabsNav}> <TabsNav activeTab={activeTab} setActiveTab={setActiveTab} tabs={tabs} />
{tabs.map(tab => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={
activeTab === tab.id
? `${accountStyles.accountTabsButton} ${accountStyles.accountTabsButtonActive}`
: accountStyles.accountTabsButton
}
>
{tab.icon}
{tab.label}
</button>
))}
</nav>
</div> </div>
{activeTab === "profile" && ( {activeTab === "profile" && (
<AccountProfile /> <AccountProfile />

View File

@ -8,6 +8,7 @@ import styles from "../../styles/stat.module.css";
import DateInput from "../../components/DateInput"; import DateInput from "../../components/DateInput";
import DateFilters from "../../components/DateFilters"; import DateFilters from "../../components/DateFilters";
import AuthGuard from "../../components/AuthGuard"; import AuthGuard from "../../components/AuthGuard";
import TabsNav from "../../components/TabsNav";
const tabs = [ const tabs = [
{ id: "agents", label: "Агенты" }, { id: "agents", label: "Агенты" },
@ -40,17 +41,7 @@ export default function StatPage() {
<h1 className={styles.title}>Статистика и аналитика</h1> <h1 className={styles.title}>Статистика и аналитика</h1>
{/* <button className={styles.exportBtn}>Экспорт</button> */} {/* <button className={styles.exportBtn}>Экспорт</button> */}
</div> </div>
<div className={styles.tabs}> <TabsNav activeTab={activeTab} setActiveTab={setActiveTab} tabs={tabs} />
{tabs.map((tab) => (
<button
key={tab.id}
className={activeTab === tab.id ? styles.activeTab : styles.tab}
onClick={() => setActiveTab(tab.id)}
>
{tab.label}
</button>
))}
</div>
<DateFilters <DateFilters
dateStart={filters.dateStart} dateStart={filters.dateStart}

View File

@ -1,4 +1,6 @@
import React from "react"; import React from "react";
import { CalendarToday } from "@mui/icons-material";
import styles from "../styles/dateinput.module.css";
interface DateInputProps { interface DateInputProps {
label: string; label: string;
@ -11,13 +13,28 @@ interface DateInputProps {
const DateInput: React.FC<DateInputProps> = ({ label, value, onChange, min, max }) => ( const DateInput: React.FC<DateInputProps> = ({ label, value, onChange, min, max }) => (
<div> <div>
<label>{label}</label> <label>{label}</label>
<input <div style={{ position: "relative" }}>
type="date" <input
value={value} type="date"
onChange={onChange} value={value}
min={min} onChange={onChange}
max={max} min={min}
/> max={max}
className={`${styles.dateInputHiddenIcon} ${styles.dateInputBase}`}
/>
<CalendarToday
className={styles.dateIcon}
fontSize="small"
onClick={(e) => {
const inputElement = e.currentTarget.previousElementSibling as HTMLInputElement;
if (inputElement && typeof inputElement.showPicker === 'function') {
inputElement.showPicker();
} else {
inputElement.focus();
}
}}
/>
</div>
</div> </div>
); );

View File

@ -5,6 +5,8 @@ import styles from "../styles/navigation.module.css";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useUser } from "./UserContext"; import { useUser } from "./UserContext";
import TabsNav from "./TabsNav";
import { useRouter } from "next/navigation";
interface NavItem { interface NavItem {
id: string; id: string;
@ -22,6 +24,7 @@ const Navigation: React.FC = () => {
const pathname = usePathname(); const pathname = usePathname();
const [login, setLogin] = useState<string>(""); const [login, setLogin] = useState<string>("");
const { firstName, surname } = useUser(); const { firstName, surname } = useUser();
const router = useRouter();
useEffect(() => { useEffect(() => {
if (typeof document !== "undefined") { if (typeof document !== "undefined") {
@ -30,25 +33,21 @@ const Navigation: React.FC = () => {
} }
}, []); }, []);
const handleNavigationChange = (tabId: string) => {
if (tabId === "home") {
router.push("/");
} else if (tabId === "stat") {
router.push("/stat");
} else if (tabId === "billing") {
router.push("/billing");
}
};
if (pathname === "/auth") return null; if (pathname === "/auth") return null;
return ( return (
<nav className={styles.nav}> <nav className={styles.nav}>
<div className={styles.logo}>RE:Premium Partner</div> <div className={styles.logo}>RE:Premium Partner</div>
<div className={styles.links}> <TabsNav activeTab={pathname} setActiveTab={handleNavigationChange} tabs={navItems} />
{navItems.map((item) => (
<Link
key={item.id}
href={item.href}
className={
pathname === item.href
? styles.active
: styles.link
}
>
{item.label}
</Link>
))}
</div>
<div className={styles.profile}> <div className={styles.profile}>
<Link href="/account" style={{ display: 'flex', alignItems: 'center', gap: 12, textDecoration: 'none' }}> <Link href="/account" style={{ display: 'flex', alignItems: 'center', gap: 12, textDecoration: 'none' }}>
<div className={styles.avatar}> <div className={styles.avatar}>

View File

@ -0,0 +1,71 @@
import React from "react";
import Link from "next/link";
import defaultTabsStyles from "../styles/tabs.module.css";
interface TabItem {
id: string;
label: string;
href?: string;
icon?: React.ReactNode;
}
interface TabsNavProps {
activeTab: string;
setActiveTab: (tabId: string) => void;
tabs: TabItem[];
tabStyles?: {
nav: string;
button: string;
buttonActive: string;
};
}
const TabsNav: React.FC<TabsNavProps> = ({
activeTab,
setActiveTab,
tabs,
tabStyles,
}) => {
const currentTabStyles = tabStyles || {
nav: defaultTabsStyles.tabsNav,
button: defaultTabsStyles.tabButton,
buttonActive: defaultTabsStyles.tabButtonActive,
};
return (
<nav className={currentTabStyles.nav}>
{tabs.map((tab) => (
tab.href ? (
<Link
key={tab.id}
href={tab.href}
onClick={() => setActiveTab(tab.id)}
className={
activeTab === tab.href
? `${currentTabStyles.button} ${currentTabStyles.buttonActive}`
: currentTabStyles.button
}
>
{tab.icon}
{tab.label}
</Link>
) : (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={
activeTab === tab.id
? `${currentTabStyles.button} ${currentTabStyles.buttonActive}`
: currentTabStyles.button
}
>
{tab.icon}
{tab.label}
</button>
)
))}
</nav>
);
};
export default TabsNav;

View File

@ -258,6 +258,7 @@
font-weight: 500; font-weight: 500;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center;
gap: 8px; gap: 8px;
cursor: pointer; cursor: pointer;
margin-top: 8px; margin-top: 8px;
@ -273,6 +274,7 @@
padding: 0; padding: 0;
display: flex; display: flex;
align-items: center; align-items: center;
color: #6b7280;
} }
/* --- Стили для вкладки уведомлений --- */ /* --- Стили для вкладки уведомлений --- */
@ -362,9 +364,11 @@
left: 22px; left: 22px;
} }
/* --- Стили для табов и навигации из page.tsx --- */
.accountTabsNav {
/* Стили для табов и навигации из page.tsx */
/* .accountTabsNav {
display: flex; display: flex;
gap: 32px; gap: 32px;
border-bottom: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb;
@ -389,51 +393,18 @@
border-bottom: 2px solid #2563eb; border-bottom: 2px solid #2563eb;
color: #2563eb; color: #2563eb;
font-weight: 600; font-weight: 600;
} } */
/* Стили для кнопок подтверждения */ /* Стили для кнопок подтверждения */
.primaryButton { .primaryButton {
background-color: #2563eb; /* Синий */ background: #2563eb;
color: #ffffff; color: #fff;
border: none; border: none;
border-radius: 6px; border-radius: 6px;
padding: 8px 16px; padding: 8px 20px;
font-weight: 500; font-weight: 500;
display: flex;
align-items: center;
gap: 8px;
cursor: pointer; cursor: pointer;
transition: background-color 0.2s ease;
} }
.primaryButton:hover {
background-color: #1d4ed8;
}
.secondaryButton {
background-color: #f3f4f6; /* Серый */
color: #374151;
border: 1px solid #d1d5db;
border-radius: 6px;
padding: 8px 16px;
font-weight: 500;
cursor: pointer;
transition: background-color 0.2s ease;
}
.secondaryButton:hover {
background-color: #e5e7eb;
}
.tertiaryButton {
background: none;
color: #6b7280; /* Темно-серый */
border: none;
padding: 8px 16px;
font-weight: 500;
cursor: pointer;
transition: color 0.2s ease;
}
.tertiaryButton:hover {
color: #4b5563;
}
/* ... можно добавить другие стили по необходимости ... */

View File

@ -0,0 +1,37 @@
.dateInputHiddenIcon {
-webkit-appearance: none; /* Safari и Chrome */
-moz-appearance: none; /* Firefox */
appearance: none; /* Стандартное свойство */
}
.dateInputHiddenIcon::-webkit-calendar-picker-indicator {
display: none; /* Скрыть для WebKit-браузеров */
}
.dateInputHiddenIcon::-moz-calendar-picker-indicator {
display: none; /* Скрыть для Mozilla-браузеров */
}
.dateInputHiddenIcon::-ms-calendar-picker-indicator {
display: none; /* Скрыть для Internet Explorer/Edge */
}
.dateInputBase {
width: 100%;
padding: 8px;
border: 1px solid #e5e7eb;
border-radius: 6px;
margin-top: 4px;
box-sizing: border-box;
padding-right: 40px;
cursor: pointer;
}
.dateIcon {
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
color: #6b7280;
}

View File

@ -13,7 +13,7 @@
font-weight: bold; font-weight: bold;
color: #2563eb; color: #2563eb;
} }
.links { /* .links {
display: flex; display: flex;
gap: 32px; gap: 32px;
} }
@ -34,7 +34,7 @@
color: #2563eb; color: #2563eb;
border-bottom: 2px solid #2563eb; border-bottom: 2px solid #2563eb;
font-weight: 600; font-weight: 600;
} } */
.profile { .profile {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -27,11 +27,14 @@
.exportBtn:hover { .exportBtn:hover {
background: #1d4ed8; background: #1d4ed8;
} }
.tabs { /* Tabs */
/* .tabs {
display: flex; display: flex;
gap: 32px; gap: 32px;
border-bottom: 1.5px solid #e5e7eb; border-bottom: 1.5px solid #e5e7eb;
margin-bottom: 24px;
} }
.tab { .tab {
background: none; background: none;
border: none; border: none;
@ -43,17 +46,19 @@
cursor: pointer; cursor: pointer;
transition: color 0.2s, border 0.2s; transition: color 0.2s, border 0.2s;
} }
.tab:hover { .tab:hover {
color: #2563eb; color: #2563eb;
border-bottom: 2px solid #dbeafe; border-bottom: 2px solid #dbeafe;
} }
.activeTab { .activeTab {
color: #2563eb; color: #2563eb;
border: none; border: none;
border-bottom: 2px solid #2563eb; border-bottom: 2px solid #2563eb;
font-weight: 600; font-weight: 600;
background: none; background: none;
} } */
.filters { .filters {
display: grid; display: grid;
grid-template-columns: repeat(1, 1fr); grid-template-columns: repeat(1, 1fr);

View File

@ -0,0 +1,31 @@
.tabsNav {
display: flex;
gap: 32px;
border-bottom: 1px solid #e5e7eb;
margin-bottom: 24px;
}
.tabButton {
background: none;
border: none;
border-bottom: 2px solid transparent;
color: #6b7280;
font-weight: 500;
font-size: 16px;
padding: 8px 0;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
}
.tabButton:hover {
color: #2563eb;
border-bottom: 2px solid #dbeafe;
}
.tabButtonActive {
border-bottom: 2px solid #2563eb;
color: #2563eb;
font-weight: 600;
}