Skip to content

Commit

Permalink
profile
Browse files Browse the repository at this point in the history
  • Loading branch information
briannaclarkso committed Apr 24, 2024
1 parent f6285c1 commit 3f1fc0b
Show file tree
Hide file tree
Showing 11 changed files with 407 additions and 95 deletions.
1 change: 0 additions & 1 deletion .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 29 additions & 1 deletion ReactFrontEnd/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,33 @@ import SearchList from './Components/SearchList'
import ParkDetails from './Components/ParkDetails'
import Register from './Components/Register'
import Footer from './Components/Footer'
import Profile from './Components/Profile'
import Login from './Components/Login'


// ### ORIGINAL BEFORE ROUTER ###
// This page is being used as "home" page

function App() {
// //uses useState to keep the authentication status (isLoggedIn)
// const [isLoggedIn, setIsLoggedIn] = useState(false); //????

// // when user is loged in function is called and set to true
// const handleLogin = () => {
// // actually needs logic if this is what we do?
// setIsLoggedIn(true);
// }; //?????

// // when user is loged out function is called and set to false
// const handleLogout = () => {
// // actually needs logic if this is what we do?
// setIsLoggedIn(false);
// };

// conditionally render routes.
// The /login route renders the Login page if the user is not logged in else profile is shown
// The /profile route renders the Profile page if the user is logged in else login page is shown

return (

<>
Expand All @@ -36,7 +57,14 @@ function App() {
<Route path = "search" element = {<SearchList />} />
</Route>
<Route path="/parksearch/search/:parkcode" element={<ParkDetails/>} />

<Route path="/profile" element={<Profile />}>
{/* {isLoggedIn ? <Profile onLogout={handleLogout} /> : <Redirect to="/login" />} */}
{/* redirects to login page if not logged if user goes to profile*/}
</Route>
<Route path="/login" element={<Login />}>
{/* {isLoggedIn ? <Redirect to="/profile" /> : <LoginPage onLogin={handleLogin} />} */}
{/* redirects to profile page if logged in if user goes to login*/}
</Route>
</Routes>
</BrowserRouter>
</AppProvider>
Expand Down
59 changes: 27 additions & 32 deletions ReactFrontEnd/src/Components/ParkSearch.jsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,39 @@
import React from 'react'
import SearchHeader from './SearchHeader'
// import SearchHeader from './SearchHeader'
import { Outlet } from 'react-router-dom'
import './SearchHeader.css'
// import './SearchHeader.css'
import Header from './Header'
import SearchForm from './SearchForm'

const ParkSearch = () => {
return (
<>
<SearchHeader />
<Outlet />
{/* <SearchHeader /> */}
<div>
<div className='holder'>
<header className='search-header'>
<Header />
<div className='search-header-content flex flex-c text-center text-white'>
{/* <div class='flex flex-c text-center text-white bg-h-full bg-gradient-to-r from-nps-green-900 to-green-500 background-image: url("../images/photo1.jpg") bg-no-repeat bg-center flex-col bg-fixed'> */}
{/* <h2 className='search-header-title text-capitalize'> Search for a park to visit!</h2> */}
<h2 className='text-6xl text-capitalize'> Search for a park to visit!</h2>
<SearchForm />
<p>Search by national park name, state abbreviation, or by activitie</p>
</div>
</header>

</div>
<Outlet />
</div>

</>
)
}

export default ParkSearch

// import React from 'react'
// import Header from './Header'
// import SearchForm from './SearchForm'
// import './SearchHeader.css'

// const ParkSearch = () => {
// return (
// <>
// <Header />
// <div className='holder'>
// <header className='search-header'>

// <div className='search-header-content flex flex-c text-center text-white'>
// <h2 className='search-header-title text-capitalize'>
// Search for a park to visit!
// </h2>
// <SearchForm />

// </div>

// </header>

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

// 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
217 changes: 217 additions & 0 deletions ReactFrontEnd/src/Components/Profile.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
import React from 'react'
import Header from './Header'
import { Link } from 'react-router-dom';
import { useState, useEffect } from 'react' //useState is a React Hook that lets you add a state variable to your component.
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() {
const [profile, setProfile] = useState({ username: '', password: '' });
const [loading, setLoading] = useState(true); //idk if this is necessary
const [formData, setFormData] = useState({ username: '', password: '' });
// const history = useHistory();
const navigate = useNavigate();

useEffect(() => {
const fetchProfile = async () => {
try {
const response = await axios.get('/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
} catch (error) {
console.error('Error fetching profile:', error); //lets us know if there is an error with the request
}
};

fetchProfile(); //calls fetchprofile when this runs
// }, []);
}, [profile.username]); //should make it so it only runs when this changes


const handleChange = (e) => { //updates the form data to what the user inputs
setFormData({ ...formData, [e.target.name]: e.target.value });
};

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
alert('Profile updated successfully'); //gets notification if it works or not
} catch (error) {
console.error('Error updating profile:', error);
alert('Error updating profile. Please try again.'); //oh no!
}
};

const handleLogout = () => {
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: '' });
// history.push('/login'); //brings user back to login page
navigate('/login');
}
};

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
alert('Account deleted successfully'); //yay!
// history.push('/login'); // Redirects to the login page
navigate('/login');
} catch (error) {
console.error('Error deleting account:', error);
alert('An error occurred while deleting your account. Please try again later.');
}
}
};

if (loading) { //displays "loading" when profile info is being fetched

return (
<>
<Header />
<div className="h-full bg-nps-green-300 pt-20 pb-20 px-10 rounded-md">
<h2 className="text-center font-bold text-green-900 text-3xl"> PROFILE PAGE </h2>
<h3 className="text-center font-bold text-green-900 text-3xl">Loading...</h3>
</div>;
</>
)
}



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

<Header />

<div className="h-full bg-nps-green-300 pt-20 pb-20 px-10 rounded-md">

<h2 className="text-center font-bold text-green-900 text-3xl"> PROFILE PAGE </h2>

<form onSubmit={handleSubmit} className="bg-nps-green-600 drop-shadow-2xl my-20 py-5 w-1/4 h-2/6 flex flex-col items-center text-center mx-auto rounded-2xl">

<div className="vertical-align-middle">

<div className="flex items-center mb-6">
<div className="w-1/3">
<label className="block text-green-900 font-bold text-right mb-1 pr-4" for="inline-username">
Username:
</label>
</div>
<div className="w-2/3">
{/* <input class="bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-purple-500" id="inline-full-name" type="text" defaultValue="Username"/> */}

{/* <label class="bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white ">
PatsUsername
</label> */}

<input //allows user to put in new text and save it, there is a place hold but idk if that needs to be there, mostly it's for me rn
type="text"
name="username"
value={formData.username} //from formdata usestate above
onChange={handleChange}
placeholder="Username"
/>

</div>
</div>

<div className="flex items-center mb-6">
<div className="w-1/3">
<label className="block text-green-900 font-bold text-right mb-1 pr-4" for="inline-password">
Password:
</label>
</div>
<div className="w-2/3">
{/* <input class="bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-purple-500" id="inline-password" type="password" defaultValue="**********" /> */}
{/* <label class="bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white ">
PatsPassword
</label> */}

<input
type="password" //characters are masked for security.
name="password"
value={formData.password}
onChange={handleChange}
placeholder="Password"
/>

</div>
</div>

<div className="flex ">
{/* <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. */}
{/* <button type="submit" class="shadow bg-green-700 hover:bg-green-600 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" disabled={submitting}>
{submitting ? 'Submitting...' : 'Save Changes'} If submitting is true, text displayed on button will be "Submitting..."
</button> need to add function*/}
<button type="submit" className="shadow bg-green-700 hover:bg-green-600 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded">
Save Changes
</button>

<button onClick={handleLogout} className="shadow bg-green-700 hover:bg-green-600 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded">
Logout
</button>

<button onClick={handleDeleteAccount} className="shadow bg-green-700 hover:bg-green-600 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded">
Delete Account
</button>
</div>
</div>

</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>


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


export default Profile

//showAlert - "profile updated"
//how to only have it show if logged in - in App I have a basic of maybe how that would work??? It should redirect to login
//I need to make it so that the username/password does not mess up css
// {users.name} {users.password}
//do I need to include a logout? it will then need to redirect to login page
//delete acount? will need button, function, a confirmation to delete
//windows.local storage delete / when sending a post request user.data.isnotnull //user id - forgien key
// delete local storage when loggged out -
//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
//
11 changes: 7 additions & 4 deletions ReactFrontEnd/src/Components/Search.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import React from 'react'
import { Link } from 'react-router-dom';
//import "./SearchList.css";
import './SearchHeader.css'
// import './SearchHeader.css'

const Search = (search) => {

// console.log(search.activities);
return (
<div className='search-item flex flex-column flex-sb drop-shadow-2xl bg-nps-green-500'>
// <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}>
<div className='search-item-info-item parkname fw-7 fs-18'>
{/* <div className='search-item-info-item parkname fw-7 fs-18'> */}
<div className=''>
<span>{search.fullname}</span>
</div>
</Link>
Expand All @@ -25,7 +27,8 @@ const Search = (search) => {
<span>{search.states}</span>
</div>

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

0 comments on commit 3f1fc0b

Please sign in to comment.