From 8b8c08be1bd5db1e448f24ea852e6cbf6ad16d1c Mon Sep 17 00:00:00 2001 From: magdo Date: Wed, 18 Mar 2026 00:01:04 +0100 Subject: [PATCH] react_minta --- Frontend/react_minta/README.md | 30 +++ Frontend/react_minta/index.html | 12 + Frontend/react_minta/package.json | 21 ++ Frontend/react_minta/src/App.jsx | 22 ++ Frontend/react_minta/src/api/productsApi.js | 16 ++ .../react_minta/src/components/Layout.jsx | 37 +++ .../src/components/ProductCard.jsx | 18 ++ .../react_minta/src/context/ThemeContext.jsx | 24 ++ Frontend/react_minta/src/main.jsx | 16 ++ .../react_minta/src/pages/ContactPage.jsx | 77 +++++++ Frontend/react_minta/src/pages/HomePage.jsx | 22 ++ .../src/pages/ProductDetailsPage.jsx | 65 ++++++ .../react_minta/src/pages/ProductsPage.jsx | 79 +++++++ Frontend/react_minta/src/styles.css | 210 ++++++++++++++++++ Frontend/react_minta/vite.config.js | 6 + 15 files changed, 655 insertions(+) create mode 100644 Frontend/react_minta/README.md create mode 100644 Frontend/react_minta/index.html create mode 100644 Frontend/react_minta/package.json create mode 100644 Frontend/react_minta/src/App.jsx create mode 100644 Frontend/react_minta/src/api/productsApi.js create mode 100644 Frontend/react_minta/src/components/Layout.jsx create mode 100644 Frontend/react_minta/src/components/ProductCard.jsx create mode 100644 Frontend/react_minta/src/context/ThemeContext.jsx create mode 100644 Frontend/react_minta/src/main.jsx create mode 100644 Frontend/react_minta/src/pages/ContactPage.jsx create mode 100644 Frontend/react_minta/src/pages/HomePage.jsx create mode 100644 Frontend/react_minta/src/pages/ProductDetailsPage.jsx create mode 100644 Frontend/react_minta/src/pages/ProductsPage.jsx create mode 100644 Frontend/react_minta/src/styles.css create mode 100644 Frontend/react_minta/vite.config.js diff --git a/Frontend/react_minta/README.md b/Frontend/react_minta/README.md new file mode 100644 index 0000000..092f163 --- /dev/null +++ b/Frontend/react_minta/README.md @@ -0,0 +1,30 @@ +# React frontend minta + +Ez a mini projekt a Frontend PPT React temai alapjan keszult, es bemutatja: + +- komponens alapu felepitest +- allapotkezelest useState hookkal +- adatbetoltest useEffect + Axios segitsegevel +- kliensoldali routingot React Routerrel +- Context API hasznalatat tema valtassal +- kontrollalt urlapot valos ideju validacioval + +## Inditas + +```bash +npm install +npm run dev +``` + +## Build ellenorzes + +```bash +npm run build +``` + +## Fo oldalak + +- `/` fooldal, useState szamlalo +- `/termekek` lista API-bol, szures, loading/error/allapotok +- `/termekek/:id` dinamikus route reszletoldal +- `/kapcsolat` kontrollalt form validacioval diff --git a/Frontend/react_minta/index.html b/Frontend/react_minta/index.html new file mode 100644 index 0000000..86ec0c7 --- /dev/null +++ b/Frontend/react_minta/index.html @@ -0,0 +1,12 @@ + + + + + + React Frontend Minta + + +
+ + + \ No newline at end of file diff --git a/Frontend/react_minta/package.json b/Frontend/react_minta/package.json new file mode 100644 index 0000000..a2b0296 --- /dev/null +++ b/Frontend/react_minta/package.json @@ -0,0 +1,21 @@ +{ + "name": "react-minta-frontend", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "axios": "^1.9.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.30.1" + }, + "devDependencies": { + "@vitejs/plugin-react": "^4.5.0", + "vite": "^6.3.5" + } +} \ No newline at end of file diff --git a/Frontend/react_minta/src/App.jsx b/Frontend/react_minta/src/App.jsx new file mode 100644 index 0000000..bd31568 --- /dev/null +++ b/Frontend/react_minta/src/App.jsx @@ -0,0 +1,22 @@ +import { Navigate, Route, Routes } from "react-router-dom"; +import Layout from "./components/Layout"; +import HomePage from "./pages/HomePage"; +import ProductsPage from "./pages/ProductsPage"; +import ProductDetailsPage from "./pages/ProductDetailsPage"; +import ContactPage from "./pages/ContactPage"; + +function App() { + return ( + + + } /> + } /> + } /> + } /> + } /> + + + ); +} + +export default App; diff --git a/Frontend/react_minta/src/api/productsApi.js b/Frontend/react_minta/src/api/productsApi.js new file mode 100644 index 0000000..2a33e37 --- /dev/null +++ b/Frontend/react_minta/src/api/productsApi.js @@ -0,0 +1,16 @@ +import axios from "axios"; + +const api = axios.create({ + baseURL: "https://fakestoreapi.com", + timeout: 10000 +}); + +export async function fetchProducts() { + const response = await api.get("/products"); + return response.data; +} + +export async function fetchProductById(id) { + const response = await api.get(`/products/${id}`); + return response.data; +} diff --git a/Frontend/react_minta/src/components/Layout.jsx b/Frontend/react_minta/src/components/Layout.jsx new file mode 100644 index 0000000..cd29280 --- /dev/null +++ b/Frontend/react_minta/src/components/Layout.jsx @@ -0,0 +1,37 @@ +import { NavLink } from "react-router-dom"; +import { useTheme } from "../context/ThemeContext"; + +const navItems = [ + { to: "/", label: "Fooldal" }, + { to: "/termekek", label: "Termekek" }, + { to: "/kapcsolat", label: "Kapcsolat" } +]; + +function Layout({ children }) { + const { theme, toggleTheme } = useTheme(); + + return ( +
+
+

React Frontend Minta

+ + +
+
{children}
+
+ ); +} + +export default Layout; diff --git a/Frontend/react_minta/src/components/ProductCard.jsx b/Frontend/react_minta/src/components/ProductCard.jsx new file mode 100644 index 0000000..9dd8e0f --- /dev/null +++ b/Frontend/react_minta/src/components/ProductCard.jsx @@ -0,0 +1,18 @@ +import { Link } from "react-router-dom"; + +function ProductCard({ product, onAddToCart }) { + return ( +
+ {product.title} +

{product.title}

+

{product.category}

+

{product.price.toFixed(2)} USD

+
+ + Reszletek +
+
+ ); +} + +export default ProductCard; diff --git a/Frontend/react_minta/src/context/ThemeContext.jsx b/Frontend/react_minta/src/context/ThemeContext.jsx new file mode 100644 index 0000000..e25cd11 --- /dev/null +++ b/Frontend/react_minta/src/context/ThemeContext.jsx @@ -0,0 +1,24 @@ +import { createContext, useContext, useMemo, useState } from "react"; + +const ThemeContext = createContext({ + theme: "light", + toggleTheme: () => {} +}); + +export function ThemeProvider({ children }) { + const [theme, setTheme] = useState("light"); + + const value = useMemo( + () => ({ + theme, + toggleTheme: () => setTheme((current) => (current === "light" ? "dark" : "light")) + }), + [theme] + ); + + return {children}; +} + +export function useTheme() { + return useContext(ThemeContext); +} diff --git a/Frontend/react_minta/src/main.jsx b/Frontend/react_minta/src/main.jsx new file mode 100644 index 0000000..db03ec5 --- /dev/null +++ b/Frontend/react_minta/src/main.jsx @@ -0,0 +1,16 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import { BrowserRouter } from "react-router-dom"; +import App from "./App"; +import { ThemeProvider } from "./context/ThemeContext"; +import "./styles.css"; + +ReactDOM.createRoot(document.getElementById("root")).render( + + + + + + + +); diff --git a/Frontend/react_minta/src/pages/ContactPage.jsx b/Frontend/react_minta/src/pages/ContactPage.jsx new file mode 100644 index 0000000..51d92e5 --- /dev/null +++ b/Frontend/react_minta/src/pages/ContactPage.jsx @@ -0,0 +1,77 @@ +import { useMemo, useState } from "react"; + +function ContactPage() { + const [formData, setFormData] = useState({ + name: "", + email: "", + message: "" + }); + const [submitted, setSubmitted] = useState(false); + + const errors = useMemo(() => { + const validationErrors = {}; + + if (!formData.name.trim()) { + validationErrors.name = "A nev megadasa kotelezo."; + } + + if (!formData.email.trim()) { + validationErrors.email = "Az email cim megadasa kotelezo."; + } else if (!/^\S+@\S+\.\S+$/.test(formData.email)) { + validationErrors.email = "Adj meg ervenyes email cimet."; + } + + if (formData.message.trim().length < 10) { + validationErrors.message = "Az uzenet legalabb 10 karakter legyen."; + } + + return validationErrors; + }, [formData]); + + const isValid = Object.keys(errors).length === 0; + + function handleChange(event) { + const { name, value } = event.target; + setFormData((current) => ({ ...current, [name]: value })); + setSubmitted(false); + } + + function handleSubmit(event) { + event.preventDefault(); + + if (!isValid) { + return; + } + + setSubmitted(true); + } + + return ( +
+

Kapcsolat

+

Kontrollalt urlap peldaval, valos ideju validacioval.

+ +
+ + + {errors.name &&

{errors.name}

} + + + + {errors.email &&

{errors.email}

} + + +