diff --git a/src/App.js b/src/App.js
index 816e235..af3f6ca 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,10 +1,12 @@
-import React from 'react';
-import { BrowserRouter, Route, Routes } from 'react-router-dom';
-import Header from './components/Header';
-import HomePage from './components/HomePage';
-import LoginPage from './components/LoginPage';
-import RegisterPage from './components/RegisterPage';
-import './App.css';
+import React from "react";
+import { BrowserRouter, Route, Routes } from "react-router-dom";
+import Header from "./components/Header";
+import HomePage from "./components/HomePage";
+import LoginPage from "./components/LoginPage";
+import RegisterPage from "./components/RegisterPage";
+import CategoriesPage from "./components/CategoriesPage";
+import AdminPage from "./components/AdminPage"; // 1. Импортируем компонент AdminPage
+import "./App.css";
function App() {
return (
@@ -15,7 +17,8 @@ function App() {
} />
} />
} />
- {/* Другие маршруты */}
+ } />
+ } /> {/* 2. Добавляем Route для AdminPage */}
diff --git a/src/components/AdminPage.css b/src/components/AdminPage.css
new file mode 100644
index 0000000..2849415
--- /dev/null
+++ b/src/components/AdminPage.css
@@ -0,0 +1,163 @@
+.admin-page {
+ font-family: "Arial", sans-serif;
+ margin: 0;
+ padding: 20px;
+ background-color: #f9f5f0;
+ color: #543d2d;
+}
+
+.admin-page h1 {
+ font-size: 2.5em;
+ margin-bottom: 20px;
+ color: #8b4513;
+ text-align: center;
+}
+
+.recipe-form {
+ background-color: #fff8f0;
+ border-radius: 12px;
+ padding: 20px;
+ margin-bottom: 30px;
+ box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15);
+ border: 1px solid #d3b48c;
+}
+
+.recipe-form h2 {
+ font-size: 1.8em;
+ margin-bottom: 15px;
+ color: #8b4513;
+ text-align: center;
+}
+
+.recipe-form label {
+ display: block;
+ margin-bottom: 5px;
+ font-weight: bold;
+}
+
+.recipe-form input[type="text"],
+.recipe-form textarea {
+ width: calc(100% - 20px);
+ padding: 10px;
+ margin-bottom: 15px;
+ border-radius: 7px;
+ border: 1px solid #d3b48c;
+ font-size: 1em;
+ color: #543d2d;
+ background-color: #fff;
+}
+
+.recipe-form button {
+ display: inline-block;
+ padding: 12px 24px;
+ background-color: #a8571d;
+ color: white;
+ text-decoration: none;
+ border: none;
+ border-radius: 7px;
+ font-weight: bold;
+ transition: background-color 0.3s ease;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ cursor: pointer;
+ font-size: 1em;
+}
+
+.recipe-form button:hover {
+ background-color: #70380e;
+}
+
+.recipe-form input[type="text"],
+.recipe-form textarea,
+.recipe-form button,
+.recipe-form label {
+ margin-bottom: 15px;
+}
+
+.recipe-table {
+ width: 100%;
+ border-collapse: collapse;
+ background-color: #fff8f0;
+ border-radius: 12px;
+ box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15);
+ border: 1px solid #d3b48c;
+ overflow: hidden;
+}
+
+.recipe-table h2 {
+ font-size: 1.8em;
+ margin-bottom: 15px;
+ color: #8b4513;
+ text-align: center;
+}
+
+.recipe-table th,
+.recipe-table td {
+ padding: 12px;
+ text-align: left;
+ border-bottom: 1px solid #d3b48c;
+}
+
+.recipe-table th {
+ background-color: #e6b88a;
+ color: #fff;
+ font-weight: bold;
+}
+
+.recipe-table tbody tr:nth-child(odd) {
+ background-color: #fff;
+}
+
+.recipe-table tbody tr:hover {
+ background-color: #f2dfd1;
+}
+
+.recipe-table button {
+ display: inline-block;
+ padding: 8px 16px;
+ background-color: #a8571d;
+ color: white;
+ text-decoration: none;
+ border: none;
+ border-radius: 5px;
+ font-weight: bold;
+ transition: background-color 0.3s ease;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ cursor: pointer;
+ font-size: 0.9em;
+ margin-right: 5px;
+}
+
+.recipe-table button:hover {
+ background-color: #70380e;
+}
+
+.recipe-table input[type="text"],
+.recipe-table textarea {
+ width: 100%;
+ padding: 8px;
+ border-radius: 5px;
+ border: 1px solid #d3b48c;
+ font-size: 1em;
+ color: #543d2d;
+}
+
+@media (max-width: 768px) {
+ .admin-page {
+ padding: 10px;
+ }
+ .admin-page h1 {
+ font-size: 2em;
+ }
+ .recipe-form {
+ padding: 15px;
+ }
+ .recipe-table th,
+ .recipe-table td {
+ padding: 8px;
+ font-size: 0.9em;
+ }
+ .recipe-table button {
+ padding: 6px 12px;
+ font-size: 0.8em;
+ }
+}
\ No newline at end of file
diff --git a/src/components/AdminPage.js b/src/components/AdminPage.js
new file mode 100644
index 0000000..9cf3be4
--- /dev/null
+++ b/src/components/AdminPage.js
@@ -0,0 +1,204 @@
+import React, { useState, useEffect } from "react";
+import { useNavigate } from "react-router-dom";
+import "./AdminPage.css";
+
+function AdminPage() {
+ const navigate = useNavigate();
+ const [recipes, setRecipes] = useState([]);
+ const [newRecipe, setNewRecipe] = useState({
+ name: "",
+ ingredients: "",
+ instructions: "",
+ });
+ const [editingRecipeId, setEditingRecipeId] = useState(null);
+
+ useEffect(() => {
+ const token = localStorage.getItem("token");
+ if (!token) {
+ navigate("/login");
+ }
+ }, [navigate]);
+
+ //загр рецептов
+ useEffect(() => {
+ const storedRecipes = localStorage.getItem("recipes");
+ if (storedRecipes) {
+ setRecipes(JSON.parse(storedRecipes));
+ }
+ }, []);
+
+ //сохр рецептов при изменении
+ useEffect(() => {
+ localStorage.setItem("recipes", JSON.stringify(recipes));
+ }, [recipes]);
+
+ const handleInputChange = (e, recipeId = null) => {
+ const { name, value } = e.target;
+
+ if (recipeId) {
+ setRecipes((prevRecipes) =>
+ prevRecipes.map((recipe) =>
+ recipe.id === recipeId ? { ...recipe, [name]: value } : recipe
+ )
+ );
+ } else {
+ setNewRecipe((prevState) => ({
+ ...prevState,
+ [name]: value,
+ }));
+ }
+ };
+
+ const addRecipe = (e) => {
+ e.preventDefault();
+ if (newRecipe.name && newRecipe.ingredients && newRecipe.instructions) {
+ const newRecipeWithId = { ...newRecipe, id: Date.now() };
+ setRecipes([...recipes, newRecipeWithId]);
+ setNewRecipe({ name: "", ingredients: "", instructions: "" });
+ } else {
+ alert("Пожалуйста, заполните все поля.");
+ }
+ };
+
+ const deleteRecipe = (recipeId) => {
+ if (window.confirm("Вы уверены, что хотите удалить этот рецепт?")) {
+ const updatedRecipes = recipes.filter((recipe) => recipe.id !== recipeId);
+ setRecipes(updatedRecipes);
+ }
+ };
+
+ const startEditing = (recipeId) => {
+ setEditingRecipeId(recipeId);
+ };
+
+ const stopEditing = () => {
+ setEditingRecipeId(null);
+ };
+
+ const saveRecipe = (recipeId) => {
+ const recipeIndex = recipes.findIndex(recipe => recipe.id === recipeId);
+
+ if (recipeIndex !== -1) {
+ const updatedRecipes = [...recipes];
+ updatedRecipes[recipeIndex] = {
+ ...updatedRecipes[recipeIndex],
+ name: updatedRecipes[recipeIndex].name,
+ ingredients: updatedRecipes[recipeIndex].ingredients,
+ instructions: updatedRecipes[recipeIndex].instructions
+ };
+ setRecipes(updatedRecipes);
+ localStorage.setItem("recipes", JSON.stringify(updatedRecipes));
+ }
+ stopEditing();
+ };
+
+ return (
+
+
Админ-панель
+
+
+
Добавить рецепт
+
+
+
+
+
+ );
+}
+
+export default AdminPage;
\ No newline at end of file
diff --git a/src/components/CategoriesPage.css b/src/components/CategoriesPage.css
new file mode 100644
index 0000000..e99f296
--- /dev/null
+++ b/src/components/CategoriesPage.css
@@ -0,0 +1,57 @@
+.categories-page {
+ padding: 40px;
+ margin-top: 60px;
+}
+
+.categories-page h1 {
+ text-align: center;
+ margin-bottom: 30px;
+ color: #8b4513;
+ font-size: 2.5em;
+ font-weight: bold;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+}
+
+.category-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+ gap: 30px;
+ padding: 20px;
+}
+
+.category-card {
+ display: block;
+ text-decoration: none;
+ color: #495057;
+ background-color: #fff;
+ border-radius: 12px;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+ padding: 25px;
+ text-align: center;
+}
+
+.category-card img {
+ width: 100%;
+ height: 200px;
+ object-fit: cover;
+ border-radius: 8px;
+ margin-bottom: 20px;
+}
+
+.category-card h3 {
+ font-size: 1.5em;
+ margin-bottom: 10px;
+ font-weight: 600;
+ text-transform: capitalize;
+}
+
+.category-card p {
+ font-size: 1em;
+ line-height: 1.6;
+ color: #6c757d;
+}
+
+.category-card {
+ background: linear-gradient(to bottom right, #fff, #f2f2f2);
+}
diff --git a/src/components/CategoriesPage.js b/src/components/CategoriesPage.js
new file mode 100644
index 0000000..6a6f5be
--- /dev/null
+++ b/src/components/CategoriesPage.js
@@ -0,0 +1,55 @@
+import React from "react";
+import { Link } from "react-router-dom";
+import "./CategoriesPage.css";
+
+function CategoriesPage() {
+ const categories = [
+ {
+ id: "salads",
+ name: "Салаты",
+ imageUrl: "",
+ description: "Вкусные и полезные салаты на любой вкус.",
+ },
+ {
+ id: "soups",
+ name: "Супы",
+ imageUrl: "",
+ description: "Согревающие и сытные супы.",
+ },
+ {
+ id: "main-courses",
+ name: "Основные блюда",
+ imageUrl: "",
+ description: "Разнообразие основных блюд для всей семьи.",
+ },
+ {
+ id: "desserts",
+ name: "Десерты",
+ imageUrl: "",
+ description: "Сладкие угощения для сладкоежек.",
+ },
+ ];
+
+ return (
+
+
Категории рецептов
+
+ {categories.map((category) => (
+
+ {category.imageUrl && (
+

+ )}
+
{category.name}
+ {category.description &&
{category.description}
}{" "}
+
+ ))}
+
+
+ );
+}
+
+export default CategoriesPage;
diff --git a/src/components/Header.css b/src/components/Header.css
index 73b0e05..ec0e6cf 100644
--- a/src/components/Header.css
+++ b/src/components/Header.css
@@ -1,93 +1,105 @@
header {
- background-color: #333;
- color: white;
- padding: 1rem 0;
+ background-color: #a8571d;
+ color: #f9f5f0;
+ padding: 1.2rem 0;
text-align: center;
- }
-
- .container {
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ position: relative;
+}
+
+.container {
width: 90%;
max-width: 1200px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
- }
-
- #logo a {
+}
+
+#logo a {
text-decoration: none;
- color: white;
- font-size: 1.5rem;
+ color: #f9f5f0;
+ font-size: 1.6rem;
font-weight: bold;
- }
-
- nav ul {
+ text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
+}
+
+nav ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
- }
-
- nav li {
- margin-left: 1rem;
- }
-
- nav a {
- color: white;
+}
+
+nav li {
+ margin-left: 1.2rem;
+}
+
+nav a {
+ color: #f2dfd1;
text-decoration: none;
transition: color 0.3s ease;
- }
-
- nav a:hover {
- color: #f0f0f0;
- }
-
- #search-form {
+}
+
+nav a:hover {
+ color: #fff;
+}
+
+#search-form {
display: flex;
align-items: center;
- }
-
- #search-input {
- padding: 0.5rem;
- border: none;
- border-radius: 4px;
- margin-right: 0.5rem;
- }
-
- #search-form button {
- background-color: #e44d26;
+}
+
+#search-input {
+ padding: 0.6rem;
+ border: 1px solid #d3b48c;
+ border-radius: 6px;
+ margin-right: 0.6rem;
+ background-color: #fff8f0;
+ color: #543d2d;
+}
+
+#search-input::placeholder {
+ color: #8b4513;
+}
+
+#search-form button {
+ background-color: #e67e22;
color: white;
border: none;
- padding: 0.5rem 1rem;
- border-radius: 4px;
+ padding: 0.6rem 1.2rem;
+ border-radius: 6px;
cursor: pointer;
transition: background-color 0.3s ease;
- }
-
- #search-form button:hover {
- background-color: #d13d17;
- }
-
- #auth a {
- margin-left: 1rem;
+ font-weight: bold;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
+}
+
+#search-form button:hover {
+ background-color: #d35400;
+}
+
+#auth a {
+ margin-left: 1.2rem;
text-decoration: none;
- color: white;
- }
-
- /* Мобильная адаптивность (пример) */
- @media (max-width: 768px) {
+ color: #f2dfd1;
+}
+
+#auth a:hover {
+ color: #fff;
+}
+
+@media (max-width: 768px) {
.container {
- flex-direction: column;
- align-items: flex-start;
+ flex-direction: column;
+ align-items: flex-start;
}
-
nav ul {
- flex-direction: column;
- align-items: flex-start;
+ flex-direction: column;
+ align-items: flex-start;
}
-
nav li {
- margin-left: 0;
- margin-bottom: 0.5rem;
+ margin-left: 0;
+ margin-bottom: 0.7rem;
}
- }
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/components/Header.js b/src/components/Header.js
index cba84f7..3dc8a0a 100644
--- a/src/components/Header.js
+++ b/src/components/Header.js
@@ -1,6 +1,7 @@
-import React from 'react';
-import { Link } from 'react-router-dom';
-import './Header.css';
+import React from "react";
+import { Link } from "react-router-dom";
+import "./Header.css";
+import logImage from "../img/log.png";
function Header() {
return (
@@ -8,22 +9,37 @@ function Header() {
-
![Логотип сайта]()
+