Skip to content

Commit

Permalink
final touch of search
Browse files Browse the repository at this point in the history
  • Loading branch information
briannaclarkso committed Apr 25, 2024
1 parent 3f1fc0b commit 30647d5
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 111 deletions.
14 changes: 6 additions & 8 deletions ReactFrontEnd/src/Components/ParkSearch.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import React from 'react'
// import SearchHeader from './SearchHeader'
import { Outlet } from 'react-router-dom'
// import './SearchHeader.css'
import Header from './Header'
import SearchForm from './SearchForm'

//This loads the Header at the top of the page
//Has css to import picture in the background and size of the search
//renders SearchForm when search is used
//Outlet allows the search bar to stay on the page and load the child route SearchList below it
//will remove <p> if we get enums

const ParkSearch = () => {
return (
<>
{/* <SearchHeader /> */}
<div>
<div className='holder'>
<header className='search-header'>
Expand All @@ -32,8 +35,3 @@ const ParkSearch = () => {

export default ParkSearch

//This loads the Header at the top of the page
//Has css to import picture and size of the search
//SearchForm
//Outlet allows the search bar to stay on the page and load the child route SearchList below it
//will remove <p> if we get enums
41 changes: 13 additions & 28 deletions ReactFrontEnd/src/Components/Profile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { useState, useEffect } from 'react' //useState is a React Hook that lets
import axios from 'axios';
// import { useHistory } from "react-router-dom"; //"The useHistory hook gives you access to the history instance that you may use to navigate."
import { useNavigate } from 'react-router-dom';
import { Outlet } from 'react-router-dom'



function Profile() {
Expand All @@ -19,7 +17,7 @@ function Profile() {
useEffect(() => {
const fetchProfile = async () => {
try {
const response = await axios.get('/profile/'+ profile.username); //gets the users info and creates url
const response = await axios.get('http://localhost:8080/profile/'+ profile.username); //gets the users info and creates url
setProfile(response.data); //set profile
setFormData(response.data); // Sets initial form data
setLoading(false); //loading is false when data is fetched, so loading is completed
Expand All @@ -40,9 +38,9 @@ function Profile() {
const handleSubmit = async (e) => { //this is when the user submits the form, it's a PUT request that saves user info
e.preventDefault();
try {
await axios.put('/profile/update', formData); // this updates the profile endpoint
const response = await axios.get('/profile/'+{username}); //fetchs updated data again
setProfile(response.data); //updates the state with new data
await axios.put('http://localhost:8080/profile/update', formData); // this updates the profile endpoint
const response = await axios.get('/profile/' + formData.username); //fetchs updated data again
setProfile(response.data); //updates the state with new data
alert('Profile updated successfully'); //gets notification if it works or not
} catch (error) {
console.error('Error updating profile:', error);
Expand All @@ -54,8 +52,8 @@ function Profile() {
if (window.confirm('Are you sure you want to log out?')) { //popup to comfirm
localStorage.removeItem('userData'); //or "token-info instead? clear out userdata from local storage
alert('Logout successfull');
setProfile({ username: '', password: '' }); //this resets the state idk if we need this because of this [profile.username]); above
setFormData({ username: '', password: '' });
// setProfile({ username: '', password: '' }); //this resets the state idk if we need this because of this [profile.username]); above
// setFormData({ username: '', password: '' });
// history.push('/login'); //brings user back to login page
navigate('/login');
}
Expand All @@ -64,10 +62,11 @@ function Profile() {
const handleDeleteAccount = async () => {
if (window.confirm('Are you sure you want to delete your account? This action cannot be undone.')) { //creates a pop up to virify user wants to delete
try {
await axios.delete('/profile/delete'); // Delete profile endpoint
// await axios.delete('/profile/delete'); // Delete profile endpoint
await axios.delete('http://localhost:8080/profile/delete/' + profile.username);
alert('Account deleted successfully'); //yay!
// history.push('/login'); // Redirects to the login page
navigate('/login');
navigate('/home');
} catch (error) {
console.error('Error deleting account:', error);
alert('An error occurred while deleting your account. Please try again later.');
Expand All @@ -92,7 +91,7 @@ function Profile() {

// const Profile = () => {
return (
<div>

<>

<Header />
Expand Down Expand Up @@ -152,7 +151,7 @@ function Profile() {
</div>
</div>

<div className="flex ">
<div className="flex items-center mb-6 ">
{/* <div class="w-1/3"></div> */}
<div className="w-2/3">
{/* conditionally disables button if submitting is true, button will disable, stops users from clicking it. prevents multiple form submissions while a request is being processed. */}
Expand All @@ -176,22 +175,9 @@ function Profile() {
</div>

</form>


{/* <div name="button group" className="flex justify-evenly">
<button className="bg-yellow-300 rounded-3xl">Favorites</button>
<Link to = "/createreview"><button className="bg-yellow-300 rounded-3xl">Reviews</button></Link>
<Link to = "/itinerary"><button className=" bg-yellow-300 rounded-3xl">Itinerearies</button></Link>
</div> */}
{/* //come back and change link of itinerary and reviews */}
{/* should this have the buttons? or should it just have logout and delete buttons? */}

</div>

</div></>

</>
<Outlet />
</div>
)
}

Expand All @@ -209,9 +195,8 @@ export default Profile
//get authinticated
//will add outlet to load reviews favs and itineraries
//add notes on how things work
//change ot react query ???
//do we need to add @Size(min =5, max = 20) to username and password - in backend and front end
//ask if i set up sql right
//eventlistener??
//trim off white space before sending
//
//login page should use naviage to go to profile or home
42 changes: 37 additions & 5 deletions ReactFrontEnd/src/Components/Search.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
import React from 'react'
import { useState } from 'react';
import { Link } from 'react-router-dom';
//import "./SearchList.css";
// import './SearchHeader.css'

// This is responsible for rendering a search item which includes image, park name, state, and activities.
//I use map on activities so that it lists all activities not just one
// the park name(fullname) is linked to the park details page
//I've also made it so that only 3 activities show at a time and you have to clikc show more to show all of them

const Search = (search) => {

// console.log(search.activities);
const [showAllActivities, setShowAllActivities] = useState(false);

const toggleActivities = () => {
setShowAllActivities(!showAllActivities);
};


return (
// <div className='search-item flex flex-column flex-sb drop-shadow-2xl bg-nps-green-500'>
<div className='p-12 rounded-3xl flex flex-column flex-sb drop-shadow-2xl bg-nps-green-500'>

<div className='search-item-img'>
<img src = {search.cover_id} alt = "photo" />
</div>

<div className='search-item-info text-center'>
<Link to = {`${search.parkcode}`} {...search}>
<Link to = {`${search.parkcode}`} {...search}>
{/* <div className='search-item-info-item parkname fw-7 fs-18'> */}
<div className=''>
<div className='underline'>
<span>{search.fullname}</span>
</div>
</Link>
Expand All @@ -28,15 +42,33 @@ const Search = (search) => {
</div>

{/* <div className='search-item-info-item activities fs-15'> */}
<div className=''>
{/* <div className=''>
<span className='text-capitalize fw-7'>Activities: </span>
<span>{search.activities.map((activitie) => {
return activitie.name + ", "
})}
</span> */}

<div>
<span className='text-capitalize fw-7'>Activities: </span>
{showAllActivities ? (
search.activities.map((activity) => (
<span key={activity.id}>{activity.name}, </span>
))
) : (
search.activities.slice(0, 3).map((activity) => (
<span key={activity.id}>{activity.name}, </span>
))
)}
{search.activities.length > 3 && (
<span onClick={toggleActivities} className="text-green-900 underline font-bold cursor-pointer">
{showAllActivities ? 'Show less' : 'Show more'}
</span>
)}
</div>

</div>
{/* </div> */}

</div>
</div>
Expand Down
43 changes: 12 additions & 31 deletions ReactFrontEnd/src/Components/SearchForm.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import React, {useRef, useEffect, useState} from 'react';
import React, {useRef, useEffect, useState} from 'react'; //manages state and side effects
import { FaSearch } from "react-icons/fa"
import { useNavigate } from 'react-router-dom'
import { useGlobalContext } from '../context'
//import "./SearchForm.css";
// import './SearchHeader.css'
import { Dropdown } from 'flowbite-react';

//this is responsible for rendering the search input field and handling search functionality
// This provides the search form interface and
// allows users to input a search term and then trigger the search
// It updates the application state and then has the search load to display search results

const SearchForm = () => {

const {setSearchTerm} = useGlobalContext();
const searchText = useRef('');
const {setSearchTerm} = useGlobalContext();
const searchText = useRef(''); //input
const navigate = useNavigate();
const [stateSearch, setStateSearch] = useState('');


useEffect(() => searchText.current.focus(), []);

Expand All @@ -21,8 +25,8 @@ const SearchForm = () => {
let tempSearchTerm = searchText.current.value.trim(); //removes whitespace from both ends of this string and returns a new string

if(tempSearchTerm === ''){
setSearchTerm("Yellowstone"); //defualt searchterm ---there is a defualt now but 3 results with 1 being yellowstone?

setSearchTerm("park"); //defualt searchterm
//setSearchTerm is from global context that sets the search term
} else {
setSearchTerm(tempSearchTerm);
}
Expand All @@ -45,14 +49,9 @@ const SearchForm = () => {
{/* <input type = "text" className='form-control text-gray-500 w-full' placeholder='Yellowstone Park ...' ref = {searchText}/> */}
<input type = "text" className='text-gray-500 w-full text-4xl p-px' placeholder='Yellowstone Park ...' ref = {searchText}/>
<button type = "submit" className='flex flex-c' onClick={handleSubmit}>
<FaSearch className='text-black' size = {32} />
<FaSearch className='text-black' size = {32} />
</button>

<div className="card flex justify-content-center">
<Dropdown ref={searchState} onChange={(e) => setStateSearch(e.value)} options={states} optionLabel="name"
placeholder="Select a State" className="w-full md:w-14rem" />
</div>

</div>
</form>
// </div>
Expand All @@ -62,21 +61,3 @@ const SearchForm = () => {
}

export default SearchForm

// const {setSearchTerm, setResultSearch} = useGlobalContext();
// const searchText = useRef('');
// const navigate = useNavigate();

// useEffect(() => searchText.current.focus(), []);
// const handleSubmit = (e) => {
// e.preventDefault(); //actually allows the search not just the defualt
// let tempSearchTerm = searchText
// if(tempSearchTerm.length === 0){
// setSearchTerm("yellowstone"); //defualt searchterm
// setResultSearch("Please enter something");
// } else {
// setSearchTerm(searchText.current.value);
// }

// navigate("/parksearch/search");
// };
23 changes: 0 additions & 23 deletions ReactFrontEnd/src/Components/SearchHeader.jsx

This file was deleted.

20 changes: 8 additions & 12 deletions ReactFrontEnd/src/Components/SearchList.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import React from 'react';
import { useGlobalContext } from '../context';
import Search from "./Search";
// import coverImg from "../images/photo2.jpg";
//import "./SearchList.css";
import './SearchHeader.css'

// This is a container to display the search results
// It fetches search data from globalContext in the context file
//this provides the grid styling
//the map limits the search items displayed
//it renders each item using Search, each search is assigned to it's own key it's bases on the index in the searches array

const SearchList = () => {
const {searches, resultName} = useGlobalContext();
const parksWithCovers = searches.map((singleSearch) => {
return {
...singleSearch,
// cover_img: singleSearch.cover_id ? `https://developer.nps.gov/api/v1/multimedia/galleries/assets?limit=50&q=${singleSearch.cover_id}&api_key=Wrk46hd2qqrRis6VpJA8CT12EeDczzGa9dYRBjYk` : coverImg
}
//This shows the picture in the search
});

//console.log(parksWithCovers);
const { searches, resultName } = useGlobalContext(); //accesses the searches and resultName from context

return (
// <section className='searchlist bg-nps-green-300'>
Expand All @@ -29,7 +25,7 @@ const SearchList = () => {
<div className='gap-12 grid'>
{
//limits search and shows results
parksWithCovers.slice(0, 20).map((item, index) => {
searches.slice(0, 20).map((item, index) => {
return (
<Search key = {index} {...item} />
)
Expand Down
12 changes: 8 additions & 4 deletions ReactFrontEnd/src/context.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ import { useCallback } from "react";
import { useQuery } from '@tanstack/react-query'
import axios from "axios";

//This allows components in the project to access and modify the global state related
//to search terms and search results obtained from the National Park Service API.

const URL = "https://developer.nps.gov/api/v1";
const api_key="Wrk46hd2qqrRis6VpJA8CT12EeDczzGa9dYRBjYk"


const AppContext = React.createContext();

const AppProvider = ({children}) => {
const [searchTerm, setSearchTerm] = useState("");
const [searches, setSearch] = useState([]);
const [searchTerm, setSearchTerm] = useState(""); //manages the search
const [searches, setSearch] = useState([]); //search results
const [resultName, setResultName] = useState("");

const fetchSearches = useCallback(
Expand Down Expand Up @@ -62,11 +65,12 @@ const AppProvider = ({children}) => {
}, [searchTerm]);



// useEffect triggers fetchSearches when searchTerm or fetchSearches changes.
useEffect(() => {
fetchSearches();
}, [searchTerm, fetchSearches]);

//This provides the state variables and sets to children components
return (
<AppContext.Provider value = {{
searches, setSearchTerm, resultName, setResultName,
Expand All @@ -77,7 +81,7 @@ const AppProvider = ({children}) => {
}



//this is a custom hook that accesses context values from any component within the application
export const useGlobalContext = () => {
return useContext(AppContext);
}
Expand Down

0 comments on commit 30647d5

Please sign in to comment.