diff --git a/.nginx/nginx.conf b/.nginx/nginx.conf new file mode 100644 index 0000000..90143f1 --- /dev/null +++ b/.nginx/nginx.conf @@ -0,0 +1,30 @@ +server { + listen 80 default_server; + listen [::]:80 default_server; + + root /var/www/dist; + index index.html; + + server_name russcult.anibilag.ru; + + location / { + try_files $uri /index.html; + } + + location /api/ { + proxy_pass http://192.168.1.67:5000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + + gzip on; + + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + error_page 404 /index.html; +} diff --git a/public/images/Logo-1.webp b/public/images/Logo-1.webp new file mode 100644 index 0000000..663eadc Binary files /dev/null and b/public/images/Logo-1.webp differ diff --git a/public/images/Logo-2.webp b/public/images/Logo-2.webp new file mode 100644 index 0000000..0aff6af Binary files /dev/null and b/public/images/Logo-2.webp differ diff --git a/server.zip b/server.zip deleted file mode 100644 index 0e9086a..0000000 Binary files a/server.zip and /dev/null differ diff --git a/src/App.tsx b/src/App.tsx index 4059263..6285f7b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -13,6 +13,7 @@ import { Footer } from './components/Footer'; import { AuthGuard } from './components/AuthGuard'; import { ImportArticlesPage } from "./pages/ImportArticlesPage"; + const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:5000'; function App() { diff --git a/src/components/ArticleCard.tsx b/src/components/ArticleCard.tsx index b905d30..fba8330 100644 --- a/src/components/ArticleCard.tsx +++ b/src/components/ArticleCard.tsx @@ -1,4 +1,4 @@ -import { Clock, ThumbsUp, MapPin } from 'lucide-react'; +import { Clock, ThumbsUp, MapPin, ThumbsDown } from 'lucide-react'; import { Link } from 'react-router-dom'; import { Article, CategoryTitles, CityTitles } from '../types'; import MinutesWord from './MinutesWord'; @@ -9,30 +9,28 @@ interface ArticleCardProps { } export function ArticleCard({ article, featured = false }: ArticleCardProps) { - const categoryName = CategoryTitles[article.categoryId]; return (
+ } flex flex-col`}>
{article.title} -
- - {categoryName} +
+ + {CategoryTitles[article.categoryId]} - - + + {CityTitles[article.cityId]}
- -
+

{article.excerpt}

-
+
{article.likes} + + + + {article.dislikes}
diff --git a/src/components/AuthGuard.tsx b/src/components/AuthGuard.tsx index c2902ea..cb435b6 100644 --- a/src/components/AuthGuard.tsx +++ b/src/components/AuthGuard.tsx @@ -36,7 +36,7 @@ export function AuthGuard({ children, requiredPermissions }: AuthGuardProps) {

Access Denied

- У вас нет прав на {action} статьи в {categoryId} категории. + У вас нет прав на {action} статьи в разделе {categoryId}.

diff --git a/src/components/AuthorsSection.tsx b/src/components/AuthorsSection.tsx index 157f344..9b8b6f0 100644 --- a/src/components/AuthorsSection.tsx +++ b/src/components/AuthorsSection.tsx @@ -27,14 +27,14 @@ export function AuthorsSection() {

Наши авторы

- Познакомьтесь с талантливыми писателями и экспертами, работающими для вас + Познакомьтесь с талантливыми писателями и экспертами, работающими для Вас

{authors.map((author) => ( -
-
+
+

{author.bio}

-
+
- - {author.articlesCount} статей - + + {author.articlesCount} статей +

{city ? `${CityTitles[Number(city)]} ` : ''} - {category ? `${CategoryTitles[Number(category)]} Статьи` : 'Тематические статьи'} + {category ? `${CategoryTitles[Number(category)]} Статьи` : 'Читайте сегодня'}

Статьи {Math.min((currentPage - 1) * ARTICLES_PER_PAGE + 1, totalArticles)} diff --git a/src/components/Header.tsx b/src/components/Header.tsx index a5e9e9b..dc83335 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,7 +1,9 @@ import React, { useState } from 'react'; -import { Menu, Search, X, ChevronDown } from 'lucide-react'; +import { Logo } from "./Header/Logo"; +import { Menu, Search, X, ChevronDown, Bookmark } from 'lucide-react'; import { Link, useLocation, useNavigate } from 'react-router-dom'; import { CategoryIds, CategoryTitles, CityIds, CityTitles } from '../types'; +import { useBookmarkStore } from "../stores/bookmarkStore"; export function Header() { @@ -12,6 +14,7 @@ export function Header() { const searchParams = new URLSearchParams(location.search); const currentCategory = searchParams.get('category'); const currentCity = searchParams.get('city'); + const { bookmarks } = useBookmarkStore(); const handleCityChange = (event: React.ChangeEvent) => { const city = event.target.value; @@ -50,9 +53,9 @@ export function Header() { > {isMobileMenuOpen ? :

} - -

Культура

- +
+ +
@@ -137,7 +141,7 @@ export function Header() { >
-

City

+

Столицы

diff --git a/src/components/Header/Logo.tsx b/src/components/Header/Logo.tsx index f4b6588..95373dd 100644 --- a/src/components/Header/Logo.tsx +++ b/src/components/Header/Logo.tsx @@ -1,11 +1,14 @@ import { Link } from 'react-router-dom'; -import { Palette } from 'lucide-react'; export function Logo() { return ( - - - CultureScope - + + Культура двух столиц + _____ + ); } \ No newline at end of file diff --git a/src/components/Header/MobileMenu.tsx b/src/components/Header/MobileMenu.tsx index 49d9639..d7ae615 100644 --- a/src/components/Header/MobileMenu.tsx +++ b/src/components/Header/MobileMenu.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { Link } from 'react-router-dom'; -import { Category, City } from '../../types'; +import { CityTitles, CategoryTitles } from '../../types'; interface MobileMenuProps { isOpen: boolean; - categories: Category[]; - cities: City[]; + categories: number[]; + cities: number[]; currentCategory: string | null; currentCity: string | null; onCityChange: (event: React.ChangeEvent) => void; @@ -34,7 +34,7 @@ export function MobileMenu({ {cities.map((city) => ( ))} @@ -58,12 +58,12 @@ export function MobileMenu({ key={category} to={`/?category=${category}${currentCity ? `&city=${currentCity}` : ''}`} className={`block px-3 py-2 rounded-md text-base font-medium ${ - currentCategory === category + Number(currentCategory) === category ? 'bg-blue-50 text-blue-600' : 'text-gray-600 hover:bg-gray-50' }`} > - {category} + {CategoryTitles[category]} ))}
diff --git a/src/components/Header/Navigation.tsx b/src/components/Header/Navigation.tsx index dc857bb..bcbfa7d 100644 --- a/src/components/Header/Navigation.tsx +++ b/src/components/Header/Navigation.tsx @@ -1,8 +1,8 @@ -import { Link, useLocation } from 'react-router-dom'; -import { Category } from '../../types'; +import { Link } from 'react-router-dom'; +import { CategoryTitles } from '../../types'; interface NavigationProps { - categories: Category[]; + categories: number[]; currentCategory: string | null; currentCity: string | null; } @@ -26,12 +26,12 @@ export function Navigation({ categories, currentCategory, currentCity }: Navigat key={category} to={`/?category=${category}${currentCity ? `&city=${currentCity}` : ''}`} className={`px-3 py-2 text-sm font-medium transition-colors whitespace-nowrap ${ - currentCategory === category + Number(currentCategory) === category ? 'text-blue-600 hover:text-blue-800' : 'text-gray-600 hover:text-gray-900' }`} > - {category} + {CategoryTitles[category]} ))}
diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index ee989fe..aa569fd 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -1,16 +1,14 @@ import React, { useState } from 'react'; import { Menu, X, Bookmark } from 'lucide-react'; import { Link, useLocation } from 'react-router-dom'; -import { Category, City } from '../../types'; import { Logo } from './Logo'; import { SearchBar } from './SearchBar'; import { Navigation } from './Navigation'; import { CitySelector } from './CitySelector'; import { MobileMenu } from './MobileMenu'; +import { CategoryIds, CityIds } from '../../types'; import { useBookmarkStore } from '../../stores/bookmarkStore'; -const categories: Category[] = ['Film', 'Theater', 'Music', 'Sports', 'Art', 'Legends', 'Anniversaries', 'Memory']; -const cities: City[] = ['New York', 'London']; export function Header() { const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); @@ -52,13 +50,13 @@ export function Header() {