diff --git a/client/package.json b/client/package.json index 54fb1cc..2cd1406 100644 --- a/client/package.json +++ b/client/package.json @@ -17,7 +17,6 @@ "dependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", - "@mui/icons-material": "^9.0.0", "@mui/material": "^9.0.0", "@tanstack/react-query": "^5.100.5", "@tiptap/extension-placeholder": "^3.22.5", diff --git a/client/src/app/layout/AppHeader.tsx b/client/src/app/layout/AppHeader.tsx index c1218c3..7a0b734 100644 --- a/client/src/app/layout/AppHeader.tsx +++ b/client/src/app/layout/AppHeader.tsx @@ -1,6 +1,4 @@ import { useEffect, useState } from 'react' -import Inventory2OutlinedIcon from '@mui/icons-material/Inventory2Outlined' -import MenuRoundedIcon from '@mui/icons-material/MenuRounded' import AppBar from '@mui/material/AppBar' import Badge from '@mui/material/Badge' import Box from '@mui/material/Box' @@ -13,6 +11,7 @@ import Typography from '@mui/material/Typography' import useMediaQuery from '@mui/material/useMediaQuery' import { useQuery } from '@tanstack/react-query' import { useUnit } from 'effector-react' +import { Menu, Package } from 'lucide-react' import { Link as RouterLink, useNavigate } from 'react-router-dom' import { useThemeController } from '@/app/providers/theme-controller' import { fetchMyCart } from '@/entities/cart/api/cart-api' @@ -101,7 +100,7 @@ export function AppHeader() { edge="start" sx={{ mr: 1 }} > - + )} @@ -137,7 +136,7 @@ export function AppHeader() { navigate('/me/orders')} aria-label="Заказы"> - + @@ -156,8 +155,19 @@ export function AppHeader() { )} {!isMobile && ( - - setScheme(s)} /> + + + setScheme(s)} /> + )} diff --git a/client/src/app/layout/MainLayout.tsx b/client/src/app/layout/MainLayout.tsx index 95e2bdd..ddc01f2 100644 --- a/client/src/app/layout/MainLayout.tsx +++ b/client/src/app/layout/MainLayout.tsx @@ -5,10 +5,11 @@ import Divider from '@mui/material/Divider' import Grid from '@mui/material/Grid' import Link from '@mui/material/Link' import Stack from '@mui/material/Stack' +import SvgIcon from '@mui/material/SvgIcon' import Typography from '@mui/material/Typography' import { Link as RouterLink } from 'react-router-dom' import { AppHeader } from '@/app/layout/AppHeader' -import { STORE_EMAIL, STORE_NAME, STORE_PHONE, STORE_SOCIAL_NOTE } from '@/shared/config' +import { STORE_EMAIL, STORE_NAME, STORE_PHONE, VK_URL } from '@/shared/config' export function MainLayout({ children }: PropsWithChildren) { const year = new Date().getFullYear() @@ -82,9 +83,18 @@ export function MainLayout({ children }: PropsWithChildren) { {STORE_PHONE} - - {STORE_SOCIAL_NOTE} - + + + + + VK + diff --git a/client/src/app/providers/AppProviders.tsx b/client/src/app/providers/AppProviders.tsx index e827022..ad90173 100644 --- a/client/src/app/providers/AppProviders.tsx +++ b/client/src/app/providers/AppProviders.tsx @@ -94,6 +94,31 @@ function AppThemeInner({ children }: PropsWithChildren) { h4: { fontWeight: 700 }, h5: { fontWeight: 600 }, }, + components: { + MuiButton: { + styleOverrides: { + root: { textTransform: 'none', borderRadius: 12, fontWeight: 600 }, + contained: { + boxShadow: '0 4px 14px 0 rgba(0,0,0,0.15)', + '&:hover': { + boxShadow: '0 6px 20px 0 rgba(0,0,0,0.25)', + transform: 'translateY(-1px)', + }, + }, + outlined: { + '&:hover': { boxShadow: '0 2px 8px 0 rgba(0,0,0,0.1)' }, + }, + }, + }, + MuiIconButton: { + styleOverrides: { + root: { + transition: 'all 0.2s ease', + '&:hover': { transform: 'scale(1.1)' }, + }, + }, + }, + }, }), [controller.resolvedMode, controller.scheme], ) diff --git a/client/src/entities/info/api/info-page-api.ts b/client/src/entities/info/api/info-page-api.ts index 0a37103..70873ac 100644 --- a/client/src/entities/info/api/info-page-api.ts +++ b/client/src/entities/info/api/info-page-api.ts @@ -1,8 +1,6 @@ import { apiClient } from '@/shared/api/client' import type { InfoPageBlock } from '../model/types' - - export async function fetchPublicInfoBlocks(): Promise<{ items: InfoPageBlock[] }> { const { data } = await apiClient.get<{ items: InfoPageBlock[] }>('info-page/blocks') return data diff --git a/client/src/features/cart/cart-badge/ui/CartBadge.tsx b/client/src/features/cart/cart-badge/ui/CartBadge.tsx index 40c2a83..a35b677 100644 --- a/client/src/features/cart/cart-badge/ui/CartBadge.tsx +++ b/client/src/features/cart/cart-badge/ui/CartBadge.tsx @@ -1,7 +1,7 @@ -import ShoppingCartRoundedIcon from '@mui/icons-material/ShoppingCartRounded' import Badge from '@mui/material/Badge' import IconButton from '@mui/material/IconButton' import Tooltip from '@mui/material/Tooltip' +import { ShoppingCart } from 'lucide-react' import type { AuthUser } from '@/shared/model/auth' type Props = { @@ -23,7 +23,7 @@ export function CartBadge({ user, cartCount, onNavigate }: Props) { aria-label="Корзина" > - + diff --git a/client/src/features/cart/toggle-cart-icon/ui/ToggleCartIcon.tsx b/client/src/features/cart/toggle-cart-icon/ui/ToggleCartIcon.tsx index 98c10e7..359999c 100644 --- a/client/src/features/cart/toggle-cart-icon/ui/ToggleCartIcon.tsx +++ b/client/src/features/cart/toggle-cart-icon/ui/ToggleCartIcon.tsx @@ -1,10 +1,8 @@ -import AddShoppingCartOutlinedIcon from '@mui/icons-material/AddShoppingCartOutlined' -import ShoppingCartOutlinedIcon from '@mui/icons-material/ShoppingCartOutlined' -import ShoppingCartRoundedIcon from '@mui/icons-material/ShoppingCartRounded' import IconButton from '@mui/material/IconButton' import Tooltip from '@mui/material/Tooltip' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useUnit } from 'effector-react' +import { ShoppingCart } from 'lucide-react' import { useNavigate } from 'react-router-dom' import { addToCart, fetchMyCart, removeCartItem } from '@/entities/cart/api/cart-api' import { $user } from '@/shared/model/auth' @@ -65,7 +63,7 @@ export function ToggleCartIcon(props: { - {user ? inCart ? : : } + {user ? (inCart ? : ) : } diff --git a/client/src/features/user/user-menu/ui/UserMenu.tsx b/client/src/features/user/user-menu/ui/UserMenu.tsx index fca6d69..65607dd 100644 --- a/client/src/features/user/user-menu/ui/UserMenu.tsx +++ b/client/src/features/user/user-menu/ui/UserMenu.tsx @@ -1,10 +1,10 @@ import { useState } from 'react' -import PersonOutlineRoundedIcon from '@mui/icons-material/PersonOutlineRounded' import Badge from '@mui/material/Badge' import IconButton from '@mui/material/IconButton' import ListItemText from '@mui/material/ListItemText' import Menu from '@mui/material/Menu' import MenuItem from '@mui/material/MenuItem' +import { User } from 'lucide-react' import type { AuthUser } from '@/shared/model/auth' type Props = { @@ -40,7 +40,7 @@ export function UserMenu({ user, onNavigate, onLogout }: Props) { invisible={!user} anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} > - + diff --git a/client/src/pages/admin-layout/ui/AdminLayoutPage.tsx b/client/src/pages/admin-layout/ui/AdminLayoutPage.tsx index a375aa2..72a6674 100644 --- a/client/src/pages/admin-layout/ui/AdminLayoutPage.tsx +++ b/client/src/pages/admin-layout/ui/AdminLayoutPage.tsx @@ -1,12 +1,5 @@ import type { ReactNode } from 'react' import { useMemo, useState } from 'react' -import AdminPanelSettingsOutlinedIcon from '@mui/icons-material/AdminPanelSettingsOutlined' -import AssignmentOutlinedIcon from '@mui/icons-material/AssignmentOutlined' -import DescriptionOutlinedIcon from '@mui/icons-material/DescriptionOutlined' -import PeopleOutlinedIcon from '@mui/icons-material/PeopleOutlined' -import PhotoLibraryOutlinedIcon from '@mui/icons-material/PhotoLibraryOutlined' -import RateReviewOutlinedIcon from '@mui/icons-material/RateReviewOutlined' -import StorefrontOutlinedIcon from '@mui/icons-material/StorefrontOutlined' import Badge from '@mui/material/Badge' import Box from '@mui/material/Box' import Divider from '@mui/material/Divider' @@ -22,6 +15,7 @@ import Typography from '@mui/material/Typography' import useMediaQuery from '@mui/material/useMediaQuery' import { useQuery } from '@tanstack/react-query' import { useUnit } from 'effector-react' +import { FileText, Image, LayoutGrid, ListOrdered, MessageSquare, Store, Users } from 'lucide-react' import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom' import { fetchAdminOrdersSummary } from '@/entities/order/api/admin-order-api' import { AdminCategoriesPage } from '@/pages/admin-categories' @@ -60,13 +54,13 @@ export function AdminLayoutPage() { const navItems: NavItem[] = useMemo( () => [ - { to: '/admin', label: 'Товары', icon: }, - { to: '/admin/categories', label: 'Категории', icon: }, - { to: '/admin/gallery', label: 'Галерея', icon: }, - { to: '/admin/orders', label: 'Заказы', icon: }, - { to: '/admin/reviews', label: 'Отзывы', icon: }, - { to: '/admin/users', label: 'Пользователи', icon: }, - { to: '/admin/info', label: 'Инфо-страница', icon: }, + { to: '/admin', label: 'Товары', icon: }, + { to: '/admin/categories', label: 'Категории', icon: }, + { to: '/admin/gallery', label: 'Галерея', icon: }, + { to: '/admin/orders', label: 'Заказы', icon: }, + { to: '/admin/reviews', label: 'Отзывы', icon: }, + { to: '/admin/users', label: 'Пользователи', icon: }, + { to: '/admin/info', label: 'Инфо-страница', icon: }, ], [], ) @@ -143,7 +137,7 @@ export function AdminLayoutPage() { bgcolor: 'warning.50', }} > - + Админка diff --git a/client/src/pages/cart/ui/CartPage.tsx b/client/src/pages/cart/ui/CartPage.tsx index 7488cd8..a952105 100644 --- a/client/src/pages/cart/ui/CartPage.tsx +++ b/client/src/pages/cart/ui/CartPage.tsx @@ -1,6 +1,3 @@ -import AddIcon from '@mui/icons-material/Add' -import DeleteOutlineOutlinedIcon from '@mui/icons-material/DeleteOutlineOutlined' -import RemoveIcon from '@mui/icons-material/Remove' import Alert from '@mui/material/Alert' import Box from '@mui/material/Box' import Button from '@mui/material/Button' @@ -11,6 +8,7 @@ import Tooltip from '@mui/material/Tooltip' import Typography from '@mui/material/Typography' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useUnit } from 'effector-react' +import { Minus, Plus, Trash2 } from 'lucide-react' import { Link as RouterLink } from 'react-router-dom' import { fetchMyCart, removeCartItem, setCartQty } from '@/entities/cart/api/cart-api' import { formatPriceRub } from '@/shared/lib/format-price' @@ -115,7 +113,7 @@ export function CartPage() { size="small" sx={{ width: 32, height: 32 }} > - + - + @@ -149,7 +147,7 @@ export function CartPage() { size="small" sx={{ width: 32, height: 32 }} > - + diff --git a/client/src/pages/home/lib/use-product-filters.ts b/client/src/pages/home/lib/use-product-filters.ts index 388ac94..d5c5ee3 100644 --- a/client/src/pages/home/lib/use-product-filters.ts +++ b/client/src/pages/home/lib/use-product-filters.ts @@ -24,8 +24,8 @@ export function useProductFilters() { return () => window.clearTimeout(t) }, [qInput]) - const handleCategoryChange = (e: SelectChangeEvent) => { - setCategorySlug(e.target.value) + const handleCategoryChange = (slug: string) => { + setCategorySlug(slug) setPage(1) } diff --git a/client/src/pages/home/ui/HomePage.tsx b/client/src/pages/home/ui/HomePage.tsx index 42acf25..70498bd 100644 --- a/client/src/pages/home/ui/HomePage.tsx +++ b/client/src/pages/home/ui/HomePage.tsx @@ -79,11 +79,13 @@ export function HomePage() { Игрушки, сувениры и другие изделия ручной работы. - + + + {productsQuery.isLoading && ( diff --git a/client/src/pages/home/ui/ProductFilters.tsx b/client/src/pages/home/ui/ProductFilters.tsx index a27a8f9..71ffe30 100644 --- a/client/src/pages/home/ui/ProductFilters.tsx +++ b/client/src/pages/home/ui/ProductFilters.tsx @@ -1,9 +1,11 @@ import { useMemo } from 'react' import Box from '@mui/material/Box' import Button from '@mui/material/Button' +import Chip from '@mui/material/Chip' import Collapse from '@mui/material/Collapse' import Divider from '@mui/material/Divider' import FormControl from '@mui/material/FormControl' +import InputAdornment from '@mui/material/InputAdornment' import InputLabel from '@mui/material/InputLabel' import MenuItem from '@mui/material/MenuItem' import Paper from '@mui/material/Paper' @@ -13,6 +15,7 @@ import TextField from '@mui/material/TextField' import ToggleButton from '@mui/material/ToggleButton' import ToggleButtonGroup from '@mui/material/ToggleButtonGroup' import Typography from '@mui/material/Typography' +import { Search, SlidersHorizontal } from 'lucide-react' import type { Category } from '@/entities/product/model/types' import type { UseProductFiltersResult } from '../lib/use-product-filters' @@ -60,31 +63,20 @@ export function ProductFilters({ spacing={2} sx={{ alignItems: { md: 'center' }, flexWrap: { md: 'wrap' } }} > - - Категория - - labelId="category-filter-label" - label="Категория" - value={categorySlug} - onChange={handleCategoryChange} - disabled={categoriesLoading} - > - - Все - - {categoriesForFilter.map((c) => ( - - {c.name} - - ))} - - - setQInput(e.target.value)} + slotProps={{ + input: { + startAdornment: ( + + + + ), + }, + }} sx={{ flexGrow: 1, minWidth: { xs: '100%', md: 360 } }} /> @@ -93,7 +85,7 @@ export function ProductFilters({ variant="outlined" sx={{ p: 1.5, - borderRadius: 2, + borderRadius: 3, bgcolor: 'background.paper', display: 'flex', flexDirection: { xs: 'column', sm: 'row' }, @@ -102,11 +94,35 @@ export function ProductFilters({ justifyContent: 'space-between', }} > - - Наличие - - Быстрый фильтр по наличию - + + + handleCategoryChange('')} + /> + {categoriesForFilter.map((c) => ( + handleCategoryChange(c.slug)} + disabled={categoriesLoading} + /> + ))} + handleAvailabilityChange(v)} sx={{ alignSelf: { xs: 'flex-start', sm: 'auto' }, - '& .MuiToggleButton-root': { px: 2, fontWeight: 700, letterSpacing: 0.2, textTransform: 'none' }, + '& .MuiToggleButton-root': { px: 1.5, fontWeight: 600, textTransform: 'none' }, '& .MuiToggleButton-root.Mui-selected': { bgcolor: 'primary.main', color: 'primary.contrastText', @@ -135,114 +151,102 @@ export function ProductFilters({ spacing={1.5} sx={{ alignItems: { sm: 'center' }, justifyContent: 'space-between', flexWrap: 'wrap' }} > - + - - - Сортировка - labelId="sort-label" label="Сортировка" value={sort} onChange={handleSortChange}> - - Сначала новые - - Цена: по возрастанию - Цена: по убыванию - - - - handlePriceMinChange(e.target.value)} - sx={{ width: { xs: '100%', md: 180 } }} - /> - handlePriceMaxChange(e.target.value)} - sx={{ width: { xs: '100%', md: 180 } }} - /> - - - На странице - - labelId="page-size-label" - label="На странице" - value={String(pageSize)} - onChange={handlePageSizeChange} - > - {[6, 12, 18, 24].map((n) => ( - - {n} + + + + Сортировка + labelId="sort-label" label="Сортировка" value={sort} onChange={handleSortChange}> + + Сначала новые - ))} - - - + Цена: по возрастанию + Цена: по убыванию + + - + handlePriceMinChange(e.target.value)} + sx={{ width: { xs: '100%', md: 160 } }} + /> + handlePriceMaxChange(e.target.value)} + sx={{ width: { xs: '100%', md: 160 } }} + /> - - - Масштаб карточек - - Выберите размер карточек в каталоге - - + + На странице + + labelId="page-size-label" + label="На странице" + value={String(pageSize)} + onChange={handlePageSizeChange} + > + {[6, 12, 18, 24].map((n) => ( + + {n} + + ))} + + + - handleCardScaleChange(v)} + + + - S - M - L - XL - + Масштаб карточек + handleCardScaleChange(v)} + sx={{ + alignSelf: { xs: 'flex-start', sm: 'auto' }, + '& .MuiToggleButton-root': { px: 1.5, fontWeight: 600, textTransform: 'none' }, + '& .MuiToggleButton-root.Mui-selected': { + bgcolor: 'primary.main', + color: 'primary.contrastText', + '&:hover': { bgcolor: 'primary.dark' }, + }, + }} + > + S + M + L + XL + + diff --git a/client/src/pages/me/ui/MeLayoutPage.tsx b/client/src/pages/me/ui/MeLayoutPage.tsx index 953c76a..d97dab6 100644 --- a/client/src/pages/me/ui/MeLayoutPage.tsx +++ b/client/src/pages/me/ui/MeLayoutPage.tsx @@ -1,10 +1,5 @@ import type { ReactNode } from 'react' import { useMemo, useState } from 'react' -import ChatOutlinedIcon from '@mui/icons-material/ChatOutlined' -import LocalShippingOutlinedIcon from '@mui/icons-material/LocalShippingOutlined' -import PlaceOutlinedIcon from '@mui/icons-material/PlaceOutlined' -import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined' -import TuneOutlinedIcon from '@mui/icons-material/TuneOutlined' import Alert from '@mui/material/Alert' import Badge from '@mui/material/Badge' import Box from '@mui/material/Box' @@ -21,6 +16,7 @@ import Typography from '@mui/material/Typography' import useMediaQuery from '@mui/material/useMediaQuery' import { useQuery } from '@tanstack/react-query' import { useUnit } from 'effector-react' +import { MapPin, MessageCircle, Settings, SlidersHorizontal, Truck } from 'lucide-react' import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom' import { fetchUnreadMessageCount } from '@/entities/user/api/messages-api' import { AddressesPage } from '@/pages/me/ui/sections/AddressesPage' @@ -56,10 +52,10 @@ export function MeLayoutPage() { const navItems: NavItem[] = useMemo( () => [ - { to: '/me/orders', label: 'Заказы', icon: }, - { to: '/me/messages', label: 'Сообщения', icon: }, - { to: '/me/settings', label: 'Настройки', icon: }, - { to: '/me/addresses', label: 'Адреса доставки', icon: }, + { to: '/me/orders', label: 'Заказы', icon: }, + { to: '/me/messages', label: 'Сообщения', icon: }, + { to: '/me/settings', label: 'Настройки', icon: }, + { to: '/me/addresses', label: 'Адреса доставки', icon: }, ], [], ) @@ -143,7 +139,7 @@ export function MeLayoutPage() { bgcolor: 'background.paper', }} > - + Профиль diff --git a/client/src/pages/product/ui/ProductPage.tsx b/client/src/pages/product/ui/ProductPage.tsx index c181eed..749084a 100644 --- a/client/src/pages/product/ui/ProductPage.tsx +++ b/client/src/pages/product/ui/ProductPage.tsx @@ -1,6 +1,4 @@ import { useMemo, useState } from 'react' -import CloseIcon from '@mui/icons-material/Close' -import StarRoundedIcon from '@mui/icons-material/StarRounded' import Alert from '@mui/material/Alert' import Box from '@mui/material/Box' import Chip from '@mui/material/Chip' @@ -14,6 +12,7 @@ import Stack from '@mui/material/Stack' import Typography from '@mui/material/Typography' import { useQuery } from '@tanstack/react-query' import { useUnit } from 'effector-react' +import { Star, X } from 'lucide-react' import { useParams } from 'react-router-dom' import { Navigation } from 'swiper/modules' import { Swiper, SwiperSlide } from 'swiper/react' @@ -180,8 +179,8 @@ export function ProductPage() { value={p.reviewsSummary.avgRating ?? 0} readOnly precision={0.25} - icon={} - emptyIcon={} + icon={} + emptyIcon={} /> {reviewsCountRu(p.reviewsSummary.approvedReviewCount)} @@ -211,8 +210,8 @@ export function ProductPage() { value={rv.rating} readOnly size="small" - icon={} - emptyIcon={} + icon={} + emptyIcon={} /> {body ? ( @@ -259,7 +258,7 @@ export function ProductPage() { sx={{ position: 'absolute', top: 12, right: 12, zIndex: 2, color: 'white' }} aria-label="Закрыть" > - + { /** Демо-контакты для футера; при необходимости задайте через VITE_* в `.env`. */ export const STORE_EMAIL = import.meta.env.VITE_STORE_EMAIL ?? 'hello@example.com' export const STORE_PHONE = import.meta.env.VITE_STORE_PHONE ?? '+7 (900) 000-00-00' -export const STORE_SOCIAL_NOTE = import.meta.env.VITE_STORE_SOCIAL_NOTE ?? 'Соцсети: укажите ссылки при публикации' +export const VK_URL = import.meta.env.VITE_VK_URL ?? '#' diff --git a/client/src/shared/ui/ModeSwitcher/ModeSwitcher.tsx b/client/src/shared/ui/ModeSwitcher/ModeSwitcher.tsx index 2f70c70..1d85c3e 100644 --- a/client/src/shared/ui/ModeSwitcher/ModeSwitcher.tsx +++ b/client/src/shared/ui/ModeSwitcher/ModeSwitcher.tsx @@ -1,7 +1,6 @@ -import DarkModeOutlinedIcon from '@mui/icons-material/DarkModeOutlined' -import LightModeOutlinedIcon from '@mui/icons-material/LightModeOutlined' import IconButton from '@mui/material/IconButton' import Tooltip from '@mui/material/Tooltip' +import { Monitor, Moon, Sun } from 'lucide-react' import type { ThemeModePreference } from '@/shared/model/theme' type Props = { @@ -22,10 +21,12 @@ function getModeLabel(mode: ThemeModePreference, resolvedMode: 'light' | 'dark') } export function ModeSwitcher({ mode, resolvedMode, onCycleMode }: Props) { + const icon = mode === 'system' ? : resolvedMode === 'dark' ? : + return ( - {resolvedMode === 'dark' ? : } + {icon} ) diff --git a/client/src/shared/ui/RichTextMessageEditor.tsx b/client/src/shared/ui/RichTextMessageEditor.tsx index f9ee69c..00f6a48 100644 --- a/client/src/shared/ui/RichTextMessageEditor.tsx +++ b/client/src/shared/ui/RichTextMessageEditor.tsx @@ -1,13 +1,11 @@ import { useEffect } from 'react' -import FormatBoldOutlinedIcon from '@mui/icons-material/FormatBoldOutlined' -import FormatItalicOutlinedIcon from '@mui/icons-material/FormatItalicOutlined' -import FormatListBulletedOutlinedIcon from '@mui/icons-material/FormatListBulletedOutlined' import Box from '@mui/material/Box' import IconButton from '@mui/material/IconButton' import Stack from '@mui/material/Stack' import Placeholder from '@tiptap/extension-placeholder' import { EditorContent, useEditor } from '@tiptap/react' import TiptapStarterKit from '@tiptap/starter-kit' +import { Bold, Italic, List } from 'lucide-react' type RichTextMessageEditorProps = { value: string @@ -59,7 +57,7 @@ export function RichTextMessageEditor({ disabled={disabled} aria-label="Жирный" > - + - + - + diff --git a/client/src/shared/ui/SchemeSwitcher/SchemeSwitcher.tsx b/client/src/shared/ui/SchemeSwitcher/SchemeSwitcher.tsx index a2abc5f..62e1f0e 100644 --- a/client/src/shared/ui/SchemeSwitcher/SchemeSwitcher.tsx +++ b/client/src/shared/ui/SchemeSwitcher/SchemeSwitcher.tsx @@ -1,4 +1,3 @@ -import CheckCircleRoundedIcon from '@mui/icons-material/CheckCircleRounded' import Box from '@mui/material/Box' import IconButton from '@mui/material/IconButton' import { Cherry, Hammer, Trees, WavesHorizontal } from 'lucide-react' @@ -11,10 +10,10 @@ type Props = { } const SCHEMES: { key: ColorScheme; color: string; label: string; icon: React.ReactNode }[] = [ - { key: 'craft', color: '#6D4C41', label: 'Крафт', icon: }, - { key: 'forest', color: '#2E7D32', label: 'Лес', icon: }, - { key: 'ocean', color: '#1565C0', label: 'Океан', icon: }, - { key: 'berry', color: '#7B1FA2', label: 'Ягоды', icon: }, + { key: 'craft', color: '#6D4C41', label: 'Крафт', icon: }, + { key: 'forest', color: '#2E7D32', label: 'Лес', icon: }, + { key: 'ocean', color: '#1565C0', label: 'Океан', icon: }, + { key: 'berry', color: '#7B1FA2', label: 'Ягоды', icon: }, ] export function SchemeSwitcher({ value, onChange, orientation = 'horizontal' }: Props) { @@ -23,7 +22,7 @@ export function SchemeSwitcher({ value, onChange, orientation = 'horizontal' }: sx={{ display: 'flex', flexDirection: orientation === 'vertical' ? 'column' : 'row', - gap: 0.5, + gap: 1, alignItems: 'center', }} > @@ -36,23 +35,24 @@ export function SchemeSwitcher({ value, onChange, orientation = 'horizontal' }: size="small" title={s.label} sx={{ - width: 30, - height: 30, - minWidth: 30, - bgcolor: s.color, + width: 36, + height: 36, + minWidth: 36, + bgcolor: 'transparent', border: 2, - borderColor: active ? 'common.white' : 'rgba(255,255,255,0.4)', - boxShadow: active ? `0 0 0 1.5px ${s.color}, 0 0 8px ${s.color}99` : 'none', - transform: active ? 'scale(1.1)' : 'scale(1)', - color: 'common.white', + borderColor: active ? s.color : 'transparent', + boxShadow: active ? `0 0 8px ${s.color}66` : 'none', + transform: active ? 'scale(1.15)' : 'scale(1)', + color: active ? s.color : 'text.secondary', transition: 'all 0.2s ease', '&:hover': { transform: 'scale(1.2)', - bgcolor: s.color, + borderColor: s.color, + color: s.color, }, }} > - {active ? : s.icon} + {s.icon} ) })} diff --git a/client/src/widgets/catalog-slider/ui/CatalogSlider.tsx b/client/src/widgets/catalog-slider/ui/CatalogSlider.tsx index 7ebf236..23e2658 100644 --- a/client/src/widgets/catalog-slider/ui/CatalogSlider.tsx +++ b/client/src/widgets/catalog-slider/ui/CatalogSlider.tsx @@ -80,24 +80,22 @@ function CatalogSliderInner({ slides }: { slides: CatalogSliderSlide[] }) { 1 ? 20 : 0, zIndex: 4, - pt: 4, - pb: slides.length > 1 ? 2 : 2, - WebkitTextStroke: '0.5px white', - // background: 'linear-gradient(to top, rgba(0,0,0,0.82) 0%, rgba(0,0,0,0.4) 50%, transparent 100%)', + background: 'linear-gradient(transparent, rgba(0,0,0,0.75))', + px: 3, + py: 2.5, }} > {captionText} diff --git a/client/src/widgets/navigation-drawer/ui/NavigationDrawer.tsx b/client/src/widgets/navigation-drawer/ui/NavigationDrawer.tsx index 42968b7..2d61e6a 100644 --- a/client/src/widgets/navigation-drawer/ui/NavigationDrawer.tsx +++ b/client/src/widgets/navigation-drawer/ui/NavigationDrawer.tsx @@ -92,8 +92,8 @@ export function NavigationDrawer({ - - + + diff --git a/docs/superpowers/plans/2026-05-14-ui-style-refresh.md b/docs/superpowers/plans/2026-05-14-ui-style-refresh.md new file mode 100644 index 0000000..eeb4d58 --- /dev/null +++ b/docs/superpowers/plans/2026-05-14-ui-style-refresh.md @@ -0,0 +1,45 @@ +# UI Style Refresh — Implementation Plan + +**Goal:** Замена иконок MUI→Lucide, редизайн темы/слайдера/фильтров/кнопок, VK в футер. + +**Architecture:** 6 независимых этапов: подготовка (package.json, config), замена иконок в ~12 файлах, визуальный редизайн 3 компонентов. + +**Tech Stack:** React, MUI, Lucide React + +--- + +### Task A1: package.json + shared/config +- Удалить `@mui/icons-material` из package.json +- Заменить `STORE_SOCIAL_NOTE` на `VK_URL` в config + +### Task A2: MUI-тема (AppProviders) +- Добавить `components.MuiButton` styleOverrides (тени, hover) +- Добавить `components.MuiIconButton` styleOverrides (scale) + +### Task B3: Хедер + меню +- `AppHeader.tsx` — `Menu`, `Package` (lucide) +- `CartBadge.tsx` — `ShoppingCart` (lucide) +- `UserMenu.tsx` — `User` (lucide) +- `ToggleCartIcon.tsx` — `ShoppingCart`, `ShoppingCartOff` (lucide) + +### Task B4: Админка +- `AdminLayoutPage.tsx` — `Store`, `LayoutGrid`, `Image`, `ListOrdered`, `MessageSquare`, `People`, `FileText` (lucide) + +### Task B5: Личный кабинет +- `MeLayoutPage.tsx` — `Truck`, `MessageCircle`, `Settings`, `MapPin`, `SlidersHorizontal` (lucide) + +### Task B6: Остальные иконки +- `ProductPage.tsx` — `Star`, `X` (lucide) +- `CartPage.tsx` — `Plus`, `Minus`, `Trash2` (lucide) +- `ModeSwitcher.tsx` — `Sun`, `Moon`, `Monitor` (lucide, 3 режима) +- `SchemeSwitcher.tsx` — без bgcolor, цветная обводка +- `RichTextMessageEditor.tsx` — `Bold`, `Italic`, `List` (lucide) + +### Task C7: VK в футер +- `MainLayout.tsx` — кастомный SvgIcon VK, удалить SOCIAL_NOTE + +### Task C8: ProductFilters (каталог) +- Search с иконкой, Chips категорий, компактные фильтры + +### Task C9: CatalogSlider (слайдер) +- Подложка с градиентом, новый стиль текста diff --git a/docs/superpowers/specs/2026-05-14-ui-style-refresh.md b/docs/superpowers/specs/2026-05-14-ui-style-refresh.md new file mode 100644 index 0000000..3306eaf --- /dev/null +++ b/docs/superpowers/specs/2026-05-14-ui-style-refresh.md @@ -0,0 +1,55 @@ +# UI Style Refresh + +**Дата:** 2026-05-14 +**Статус:** Утверждён + +## Мотивация + +Освежить визуальный стиль сайта: заменить иконки на Lucide, переработать тему/переключатели схем, добавить VK в футер, обновить стиль каталога, слайдера и кнопок. + +## 1. Иконки: MUI → Lucide React (везде) + +Удалить зависимость `@mui/icons-material` из `client/package.json`. Все иконки MUI заменить на Lucide React. + +## 2. Theme/SchemeSwitcher + +Горизонтальное расположение. ModeSwitcher: `Sun`/`Moon`/`Monitor`. SchemeSwitcher: без bgcolor, цветная обводка у активной. + +## 3. VK в футер + +Кастомный SVG-логотип VK (`SvgIcon`), ссылка `href={VITE_VK_URL}`, удалить `STORE_SOCIAL_NOTE`. + +## 4. ProductFilters (каталог) + +Визуальный редизайн: Search с иконкой, Chips категорий, компактные фильтры, Material 3 стиль. + +## 5. CatalogSlider (слайдер) + +Подложка `rgba(0,0,0,0.7)` под текст, новый размер/вес шрифта, убрать WebkitTextStroke. + +## 6. Кнопки (MUI-тема) + +MuiButton: тени, градиент, hover-эффект. MuiIconButton: scale на hover. + +## Файлы для изменения + +| Файл | Изменение | +|---|---| +| `client/package.json` | Удалить `@mui/icons-material` | +| `client/src/app/providers/AppProviders.tsx` | MuiButton/MuiIconButton styleOverrides | +| `client/src/shared/config/index.ts` | Добавить VK_URL, удалить SOCIAL_NOTE | +| `client/src/app/layout/AppHeader.tsx` | MUI→Lucide иконки | +| `client/src/app/layout/MainLayout.tsx` | VK иконка, удалить SOCIAL_NOTE | +| `client/src/shared/ui/ModeSwitcher/ModeSwitcher.tsx` | Lucide + 3 режима | +| `client/src/shared/ui/SchemeSwitcher/SchemeSwitcher.tsx` | Убрать bgcolor, обводка | +| `client/src/features/cart/cart-badge/ui/CartBadge.tsx` | Lucide `ShoppingCart` | +| `client/src/features/cart/toggle-cart-icon/ui/ToggleCartIcon.tsx` | Lucide иконки | +| `client/src/features/user/user-menu/ui/UserMenu.tsx` | Lucide `User` | +| `client/src/widgets/navigation-drawer/ui/NavigationDrawer.tsx` | Lucide иконки | +| `client/src/widgets/catalog-slider/ui/CatalogSlider.tsx` | Подложка текста | +| `client/src/pages/home/ui/ProductFilters.tsx` | Визуальный редизайн | +| `client/src/pages/admin-layout/ui/AdminLayoutPage.tsx` | Lucide иконки | +| `client/src/pages/me/ui/MeLayoutPage.tsx` | Lucide иконки | +| `client/src/pages/products/ui/ProductPage.tsx` | Lucide `Star`, `X` | +| `client/src/pages/cart/ui/CartPage.tsx` | Lucide `Trash2`, `Plus`, `Minus` | +| `client/src/shared/ui/RichTextMessageEditor.tsx` | Lucide `Bold`, `Italic`, `List` |