From 09d88296e14e100d62d55521f82eccbfbbed266e Mon Sep 17 00:00:00 2001 From: KacperWojdak Date: Sun, 12 Jan 2025 17:37:52 +0100 Subject: [PATCH 1/5] Added displaying pages and comments for kebabs --- frontend/src/components/KebabsList.js | 42 +++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/KebabsList.js b/frontend/src/components/KebabsList.js index c4eac44..e8251a3 100644 --- a/frontend/src/components/KebabsList.js +++ b/frontend/src/components/KebabsList.js @@ -191,17 +191,53 @@ const translateStatus = (status) => { {kebab.ordering_options && kebab.ordering_options.length > 0 && ( -
-

Opcje zamówień:

+
+

Opcje zamówień:

{kebab.ordering_options.map((option, index) => ( -

+

{option}

))}
)} + + {kebab.pages && Object.keys(kebab.pages).length > 0 && ( +
+

Strony:

+
    + {Object.entries(kebab.pages).map(([key, value]) => ( +
  • + + {key} + +
  • + ))} +
+
+ )} + + {kebab.comments && kebab.comments.length > 0 && ( +
+

Komentarze:

+
+ {kebab.comments.map((commentObj, index) => ( +
+ + {commentObj.name || `Użytkownik #${commentObj.id_user}`}: + + {commentObj.comment} +
+ ))} +
+
+ )}
From 8fb7841a6eb91841ed921a5e352597afeba14e4c Mon Sep 17 00:00:00 2001 From: KacperWojdak Date: Mon, 13 Jan 2025 12:33:18 +0100 Subject: [PATCH 2/5] api url change. added pages to filters --- frontend/src/axiosClient.js | 2 +- frontend/src/components/KebabsList.js | 16 +++++----- frontend/src/components/SearchPanel.js | 42 +++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/frontend/src/axiosClient.js b/frontend/src/axiosClient.js index cecd798..8cf56ef 100644 --- a/frontend/src/axiosClient.js +++ b/frontend/src/axiosClient.js @@ -1,7 +1,7 @@ import axios from 'axios'; const axiosClient = axios.create({ - baseURL: 'https://sponge-climbing-adder.ngrok-free.app/api', + baseURL: 'https://legible-freely-wren.ngrok-free.app/api', }); axiosClient.interceptors.request.use((config) => { diff --git a/frontend/src/components/KebabsList.js b/frontend/src/components/KebabsList.js index e8251a3..4f2cb94 100644 --- a/frontend/src/components/KebabsList.js +++ b/frontend/src/components/KebabsList.js @@ -135,7 +135,7 @@ const translateStatus = (status) => { toggleDetails(index)} @@ -206,31 +206,31 @@ const translateStatus = (status) => { {kebab.pages && Object.keys(kebab.pages).length > 0 && (

Strony:

-
    +
    {Object.entries(kebab.pages).map(([key, value]) => ( -
  • +
  • +
    ))} -
+
)} {kebab.comments && kebab.comments.length > 0 && (

Komentarze:

-
+
{kebab.comments.map((commentObj, index) => (
- {commentObj.name || `Użytkownik #${commentObj.id_user}`}: + {commentObj.name || `Użytkownik #${commentObj.id_user}`}: {commentObj.comment}
diff --git a/frontend/src/components/SearchPanel.js b/frontend/src/components/SearchPanel.js index a8f77f4..e8b4aca 100644 --- a/frontend/src/components/SearchPanel.js +++ b/frontend/src/components/SearchPanel.js @@ -10,6 +10,8 @@ export default function SearchPanel({ kebabs, onSearch }) { const [selectedSauces, setSelectedSauces] = useState([]); const [selectedMeats, setSelectedMeats] = useState([]); const [selectedOrderingOptions, setSelectedOrderingOptions] = useState([]); + const [selectedPages, setSelectedPages] = useState([]); + const allSauces = Array.from( new Set(kebabs.flatMap((kebab) => kebab.sauces || [])) @@ -23,6 +25,10 @@ export default function SearchPanel({ kebabs, onSearch }) { new Set(kebabs.flatMap((kebab) => kebab.ordering_options || [])) ); + const allPages = Array.from( + new Set(kebabs.flatMap((kebab) => Object.keys(kebab.pages || {}))) + ); + const getCurrentTimeDetails = () => { const now = new Date(); const currentHour = now.getHours(); @@ -87,13 +93,22 @@ export default function SearchPanel({ kebabs, onSearch }) { applyFilters(searchQuery, selectedSauces, selectedMeats, showOpenNow, sortOrder, updatedOptions); }; + const handlePageToggle = (page) => { + const updatedPages = selectedPages.includes(page) + ? selectedPages.filter((p) => p !== page) + : [...selectedPages, page]; + + setSelectedPages(updatedPages); + applyFilters(searchQuery, selectedSauces, selectedMeats, showOpenNow, sortOrder, selectedOrderingOptions, updatedPages); + }; + const toggleOpenNow = () => { const updatedShowOpenNow = !showOpenNow; setShowOpenNow(updatedShowOpenNow); applyFilters(searchQuery, selectedSauces, selectedMeats, updatedShowOpenNow, sortOrder); }; - const applyFilters = (query, sauces, meats, openNow, order, orderingOptions = []) => { + const applyFilters = (query, sauces, meats, openNow, order, orderingOptions = [], pages = []) => { let filteredKebabs = kebabs; if (query) { @@ -120,6 +135,12 @@ export default function SearchPanel({ kebabs, onSearch }) { ); } + if (pages.length > 0) { + filteredKebabs = filteredKebabs.filter((kebab) => + pages.every((page) => Object.keys(kebab.pages || {}).includes(page)) + ); + } + if (openNow) { filteredKebabs = filteredKebabs.filter(isOpenNow); } @@ -133,6 +154,7 @@ export default function SearchPanel({ kebabs, onSearch }) { onSearch(filteredKebabs); }; + return (
@@ -249,6 +271,24 @@ export default function SearchPanel({ kebabs, onSearch }) { ))}
+ + {/* Strony */} +
+

Strony:

+
+ {allPages.map((page) => ( + + ))} +
+
From 4207a784c7d5b9470106c3bc588fc725da098e4d Mon Sep 17 00:00:00 2001 From: KacperWojdak Date: Mon, 13 Jan 2025 12:47:17 +0100 Subject: [PATCH 3/5] Added kebabs counter --- frontend/src/components/SearchPanel.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/frontend/src/components/SearchPanel.js b/frontend/src/components/SearchPanel.js index e8b4aca..f34827f 100644 --- a/frontend/src/components/SearchPanel.js +++ b/frontend/src/components/SearchPanel.js @@ -154,7 +154,18 @@ export default function SearchPanel({ kebabs, onSearch }) { onSearch(filteredKebabs); }; + + const kebabStatusCounts = () => { + const statuses = { exists: 0, closed: 0, planned: 0 }; + kebabs.forEach((kebab) => { + if (statuses[kebab.status] !== undefined) { + statuses[kebab.status]++; + } + }); + return statuses; + }; + const { exists, closed, planned } = kebabStatusCounts(); return (
@@ -165,6 +176,12 @@ export default function SearchPanel({ kebabs, onSearch }) { onChange={handleSearchChange} className="w-full p-2 border rounded-lg mb-2" /> +
+

Otwarte: {exists}

+

Zamknięte: {closed}

+

Planowane: {planned}

+
+
Sortowanie po nazwie:
diff --git a/frontend/src/pages/MapClone.js b/frontend/src/pages/MapClone.js new file mode 100644 index 0000000..6793ed0 --- /dev/null +++ b/frontend/src/pages/MapClone.js @@ -0,0 +1,92 @@ +import React, { useState, useEffect } from 'react'; +import '../index.css'; +import Header from '../components/Header.js'; +import Footer from '../components/Footer.js'; +import KebabsListClone from '../components/KebabListClone.js'; +import SearchPanel from '../components/SearchPanel.js'; +import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet'; +import L from 'leaflet'; +import 'leaflet/dist/leaflet.css'; +import kebab_icon from '../img/kebab_icon.png'; +import axiosClient from '../axiosClient.js'; + +export default function MapClone() { + const legnicaBounds = [ + [51.158, 16.114], + [51.242, 16.260], + ]; + + const [kebabs, setKebabs] = useState([]); + const [filteredKebabs, setFilteredKebabs] = useState([]); + + useEffect(() => { + axiosClient + .get('/kebabs') + .then((response) => { + setKebabs(response.data); + setFilteredKebabs(response.data); + }) + .catch((error) => { + console.error('Błąd pobierania kebabów:', error); + }); + }, []); + + const kebabIcon = new L.Icon({ + iconUrl: kebab_icon, + iconSize: [30, 30], + iconAnchor: [15, 30], + popupAnchor: [0, -30], + }); + + const handleSearch = (filtered) => { + setFilteredKebabs(filtered); + }; + + return ( +
+
+
+ {/* Mapa */} +
+ + + + {filteredKebabs.map((kebab, index) => ( + + + {kebab.name}
+ {kebab.address} +
+
+ ))} +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ ); +} diff --git a/frontend/src/router.js b/frontend/src/router.js index d5bfa20..90a34b2 100644 --- a/frontend/src/router.js +++ b/frontend/src/router.js @@ -2,6 +2,7 @@ import React from 'react'; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import Home from './pages/Home.js'; import Map from './pages/Map.js'; +import MapClone from './pages/MapClone.js'; import AuthPage from './pages/AuthPage.js'; import AdminPanel from './pages/AdminPanel.js'; import ProtectedRoute from './components/ProtectedRoute.js'; @@ -11,6 +12,7 @@ const AppRouter = () => ( } /> } /> + } /> } /> Date: Tue, 14 Jan 2025 21:26:41 +0100 Subject: [PATCH 5/5] Added details popup to map --- frontend/src/components/KebabListClone.js | 31 ++++++++++++++++++----- frontend/src/pages/MapClone.js | 25 ++++++++++++++++-- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/KebabListClone.js b/frontend/src/components/KebabListClone.js index d6c4c5a..55149a6 100644 --- a/frontend/src/components/KebabListClone.js +++ b/frontend/src/components/KebabListClone.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faArrowDown } from '@fortawesome/free-solid-svg-icons'; @@ -23,19 +23,36 @@ const translateStatus = (status) => { return statusMap[status] || 'Nieznany'; }; -export default function KebabsListClone({ kebabs }) { - const [openIndex, setOpenIndex] = useState(null); +export default function KebabsListClone({ kebabs, activeKebabIndex }) { + const [openIndex, setOpenIndex] = useState(null); + const kebabRefs = useRef([]); - const toggleDetails = (index) => { - setOpenIndex(openIndex === index ? null : index); - }; + useEffect(() => { + if (activeKebabIndex !== null) { + setOpenIndex(activeKebabIndex); + if (kebabRefs.current[activeKebabIndex]) { + kebabRefs.current[activeKebabIndex].scrollIntoView({ + behavior: 'smooth', + block: 'center', + }); + } + } + }, [activeKebabIndex]); + + const toggleDetails = (index) => { + setOpenIndex(openIndex === index ? null : index); + }; return (
{kebabs.map((kebab, index) => (
(kebabRefs.current[index] = el)} + className={`p-4 rounded-lg shadow-md bg-white ${ + activeKebabIndex === index ? 'border-2 border-blue-500' : '' + }`} >
diff --git a/frontend/src/pages/MapClone.js b/frontend/src/pages/MapClone.js index 6793ed0..790b4d4 100644 --- a/frontend/src/pages/MapClone.js +++ b/frontend/src/pages/MapClone.js @@ -18,6 +18,7 @@ export default function MapClone() { const [kebabs, setKebabs] = useState([]); const [filteredKebabs, setFilteredKebabs] = useState([]); + const [activeKebabIndex, setActiveKebabIndex] = useState(null); useEffect(() => { axiosClient @@ -42,6 +43,20 @@ export default function MapClone() { setFilteredKebabs(filtered); }; + const scrollToKebab = (index) => { + setActiveKebabIndex(index); + + setTimeout(() => { + const kebabElement = document.getElementById(`kebab-${index}`); + if (kebabElement) { + kebabElement.scrollIntoView({ + behavior: 'smooth', + block: 'center', + }); + } + }, 0); + }; + return (
@@ -70,7 +85,13 @@ export default function MapClone() { > {kebab.name}
- {kebab.address} + {kebab.address}
+
))} @@ -82,7 +103,7 @@ export default function MapClone() {
- +