167 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { Icon } from "@iconify/react";
import { useAppSelector, useAppDispatch } from "../../store/hooks";
import { clearAuth } from "../../store/slices/authSlice";
import {
setSelectedDate,
setSelectedTag,
setSearchQuery,
} from "../../store/slices/notesSlice";
import { authApi } from "../../api/authApi";
import { userApi } from "../../api/userApi";
import { ThemeToggle } from "../common/ThemeToggle";
import { setUser, setAiSettings } from "../../store/slices/profileSlice";
import { setAccentColor as setAccentColorAction } from "../../store/slices/uiSlice";
import { setAccentColor } from "../../utils/colorUtils";
interface HeaderProps {
onFilterChange?: (hasFilters: boolean) => void;
onToggleSidebar?: () => void;
}
export const Header: React.FC<HeaderProps> = ({
onFilterChange,
onToggleSidebar,
}) => {
const navigate = useNavigate();
const dispatch = useAppDispatch();
const username = useAppSelector((state) => state.auth.username);
const user = useAppSelector((state) => state.profile.user);
const selectedDate = useAppSelector((state) => state.notes.selectedDate);
const selectedTag = useAppSelector((state) => state.notes.selectedTag);
const searchQuery = useAppSelector((state) => state.notes.searchQuery);
useEffect(() => {
loadUserInfo();
}, []);
useEffect(() => {
const hasFilters = !!(selectedDate || selectedTag || searchQuery);
onFilterChange?.(hasFilters);
}, [selectedDate, selectedTag, searchQuery, onFilterChange]);
const loadUserInfo = async () => {
try {
const userData = await userApi.getProfile();
dispatch(setUser(userData));
// Устанавливаем цвет акцента из профиля пользователя
const accent = userData.accent_color || "#007bff";
dispatch(setAccentColorAction(accent));
setAccentColor(accent);
// Загружаем AI настройки
try {
const aiSettings = await userApi.getAiSettings();
dispatch(setAiSettings(aiSettings));
} catch (aiError) {
console.error("Ошибка загрузки AI настроек:", aiError);
}
} catch (error) {
console.error("Ошибка загрузки информации о пользователе:", error);
}
};
const handleLogout = async () => {
try {
await authApi.logout();
dispatch(clearAuth());
navigate("/");
} catch (error) {
console.error("Ошибка выхода:", error);
dispatch(clearAuth());
navigate("/");
}
};
const handleClearFilters = () => {
dispatch(setSelectedDate(null));
dispatch(setSelectedTag(null));
dispatch(setSearchQuery(""));
};
const hasFilters = !!(selectedDate || selectedTag || searchQuery);
// Формируем список активных фильтров
const getActiveFilters = () => {
const filters: string[] = [];
if (searchQuery) {
filters.push(`Поиск: "${searchQuery}"`);
}
if (selectedDate) {
filters.push(`Дата: ${selectedDate}`);
}
if (selectedTag) {
filters.push(`Тег: #${selectedTag}`);
}
return filters;
};
const activeFilters = getActiveFilters();
return (
<>
{/* Кнопка мобильного меню */}
{onToggleSidebar && (
<button className="mobile-menu-btn" onClick={onToggleSidebar}>
<Icon icon="mdi:menu" />
</button>
)}
<header className="notes-header">
<div className="notes-header-left">
<span>
<Icon icon="mdi:note-text" /> Мои заметки
</span>
{hasFilters && (
<div
className="filter-indicator"
style={{ display: "inline-block" }}
>
Фильтр: {activeFilters.join(", ")}{" "}
<button onClick={handleClearFilters}></button>
</div>
)}
</div>
<div className="user-info">
{user?.avatar ? (
<div
className="user-avatar-mini"
style={{ display: "block" }}
title="Перейти в профиль"
onClick={() => navigate("/profile")}
>
<img src={user.avatar} alt="Аватар" loading="lazy" />
</div>
) : (
<div
className="user-avatar-mini user-avatar-placeholder-mini"
style={{ display: "flex" }}
title="Перейти в профиль"
onClick={() => navigate("/profile")}
>
<Icon icon="mdi:account" />
</div>
)}
<ThemeToggle />
<button
className="settings-icon-btn"
title="Настройки"
onClick={() => navigate("/settings")}
>
<Icon icon="mdi:cog" />
</button>
<button className="logout-btn" title="Выйти" onClick={handleLogout}>
<Icon icon="mdi:logout" />
</button>
</div>
</header>
</>
);
};