diff --git a/client/src/App.tsx b/client/src/App.tsx index de05df1..f1ad9d6 100755 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -26,7 +26,7 @@ function App(): JSX.Element { - + diff --git a/client/src/components/NavBar/BecomeSitter/BecomeSitter.tsx b/client/src/components/NavBar/BecomeSitter/BecomeSitter.tsx index 06cbeb8..6e8efc0 100644 --- a/client/src/components/NavBar/BecomeSitter/BecomeSitter.tsx +++ b/client/src/components/NavBar/BecomeSitter/BecomeSitter.tsx @@ -37,10 +37,10 @@ const BecomeSitter = (): JSX.Element => { }; const handleChange = (event: ChangeEvent) => { - setState({ - ...state, + setState((prevState) => ({ + ...prevState, [event.target.name]: event.target.checked, - }); + })); }; const handleSitter = (event: ChangeEvent) => { @@ -49,7 +49,6 @@ const BecomeSitter = (): JSX.Element => { const handleSubmit = () => { //TODO: Placeholder for editing profile info to switch between sitter and not a sitter - console.log('hello'); setOpen(false); }; diff --git a/client/src/components/ProfileCard/ProfileCard.tsx b/client/src/components/ProfileCard/ProfileCard.tsx index 6ec08bb..80152cf 100644 --- a/client/src/components/ProfileCard/ProfileCard.tsx +++ b/client/src/components/ProfileCard/ProfileCard.tsx @@ -5,6 +5,7 @@ import CardContent from '@mui/material/CardContent'; import Typography from '@mui/material/Typography'; import picture from '../../Images/d9fc84a0d1d545d77e78aaad39c20c11d3355074.png'; import { Profile } from '../../interface/Profile'; +import { Link } from 'react-router-dom'; interface Props { profile: Profile; @@ -12,24 +13,33 @@ interface Props { const ProfileCard = ({ profile }: Props): JSX.Element => { const classes = useStyles(); + const { _id: id, firstName, lastName, description, location, hourlyRate } = profile; return ( - - - - + - - {`${profile.firstName} ${profile.lastName}`} - - - {profile.description} - + + + + + {`${firstName} ${lastName}`} + + + {description} + + + + {location} + {`${hourlyRate}/hr`} + + - - {profile.location} - $14/hr - ); }; diff --git a/client/src/components/ProfileCard/useStyles.ts b/client/src/components/ProfileCard/useStyles.ts index 1a5c939..2be35b6 100644 --- a/client/src/components/ProfileCard/useStyles.ts +++ b/client/src/components/ProfileCard/useStyles.ts @@ -1,15 +1,20 @@ import { makeStyles } from '@material-ui/core/styles'; const useStyles = makeStyles((theme) => ({ + profileCard: { + textDecoration: 'none', + overflow: 'hidden', + '&:hover': { + overflow: 'auto', + boxShadow: theme.shadows[23], + }, + }, picture: { borderRadius: '50%', width: 150, }, infoWrapper: { borderTop: '1px solid grey', - display: 'flex', - padding: 5, - justifyContent: 'space-evenly', }, })); diff --git a/client/src/helpers/APICalls/getAllProfiles.ts b/client/src/helpers/APICalls/getAllProfiles.ts new file mode 100644 index 0000000..5b51f17 --- /dev/null +++ b/client/src/helpers/APICalls/getAllProfiles.ts @@ -0,0 +1,20 @@ +import { FetchOptions } from '../../interface/FetchOptions'; +import { AllProfilesApiData } from '../../interface/Profile'; + +const getAllProfiles = async ( + searchValue: string | '', + startValue: Date | null, + endValue: Date | null, +): Promise => { + const fetchOptions: FetchOptions = { + method: 'GET', + credentials: 'include', + }; + return await fetch(`/profile/profiles?search=${searchValue}&start=${startValue}&end=${endValue}`, fetchOptions) + .then((res) => res.json()) + .catch(() => ({ + error: { message: 'Unable to connect to server. Please try again' }, + })); +}; + +export default getAllProfiles; diff --git a/client/src/pages/Dashboard/Dashboard.tsx b/client/src/pages/Dashboard/Dashboard.tsx index 8c2eb82..9746e1f 100755 --- a/client/src/pages/Dashboard/Dashboard.tsx +++ b/client/src/pages/Dashboard/Dashboard.tsx @@ -3,30 +3,44 @@ import CssBaseline from '@material-ui/core/CssBaseline'; import CircularProgress from '@material-ui/core/CircularProgress'; import useStyles from './useStyles'; import { useAuth } from '../../context/useAuthContext'; -import { useSocket } from '../../context/useSocketContext'; import { useHistory } from 'react-router-dom'; -import { useEffect } from 'react'; +import { ChangeEvent, useEffect, useState } from 'react'; import { Box, Typography } from '@material-ui/core'; import ProfileCard from '../../components/ProfileCard/ProfileCard'; -import { mockProfiles } from '../../mocks/mockProfile'; +import getAllProfiles from '../../helpers/APICalls/getAllProfiles'; +import { Profile } from '../../interface/Profile'; +import DashboardSearch from './DashboardSearch/DashboardSearch'; export default function Dashboard(): JSX.Element { const classes = useStyles(); + const [profiles, setProfiles] = useState([]); + const [searchValue, setSearchValue] = useState(''); + const [startValue, setStartValue] = useState(new Date()); + const [endValue, setEndValue] = useState(null); const { loggedInUser } = useAuth(); - const { initSocket } = useSocket(); - const history = useHistory(); - const handleSubmit = () => { - console.log('submitted'); + useEffect(() => { + getAllProfiles(searchValue, startValue, endValue).then((data) => { + setProfiles(data.profiles); + }); + }, [searchValue, startValue, endValue]); + + const handleStartDateChange = (newValue: Date | null) => { + setStartValue(newValue); }; - useEffect(() => { - initSocket(); - }, [initSocket]); + const handleEndDateChange = (newValue: Date | null) => { + setEndValue(newValue); + }; + + const handleSearchChange = (event: ChangeEvent) => { + setSearchValue(event.target.value); + }; if (loggedInUser === undefined) return ; + if (!loggedInUser) { history.push('/login'); // loading for a split seconds until history.push works @@ -38,19 +52,30 @@ export default function Dashboard(): JSX.Element { Search for Users + {/**TODO: - * 1. Each Card should be a link to the userprofile route - * 2. Currently using mock profiles, need to change to actual list of profiles from api call - **/} + * + * Currently using mock profiles, need to change to actual list of profiles from api call + ***/} - {Array.from(mockProfiles).map((_, index) => ( - - - - - - ))} + {profiles.length ? ( + Array.from(profiles).map((_, index) => ( + + + + + + )) + ) : ( + No users found. + )} ); diff --git a/client/src/pages/Dashboard/DashboardSearch/DashboardSearch.tsx b/client/src/pages/Dashboard/DashboardSearch/DashboardSearch.tsx index 9e0edba..de9cb18 100644 --- a/client/src/pages/Dashboard/DashboardSearch/DashboardSearch.tsx +++ b/client/src/pages/Dashboard/DashboardSearch/DashboardSearch.tsx @@ -8,33 +8,24 @@ import MobileDatePicker from '@mui/lab/MobileDatePicker'; import { IconButton, Typography } from '@material-ui/core'; import { SearchOutlined } from '@material-ui/icons'; -export default function DashboardSearch(): JSX.Element { +interface Props { + handleSearchChange: (event: ChangeEvent) => void; + handleStartDateChange: (newValue: Date | null) => void; + handleEndDateChange: (newValue: Date | null) => void; + startValue: Date | null; + endValue: Date | null; +} + +export default function DashboardSearch({ + handleSearchChange, + handleStartDateChange, + handleEndDateChange, + startValue, + endValue, +}: Props): JSX.Element { const classes = useStyles(); - const [cityValue, setCityValue] = useState('Search'); - const [startValue, setStartValue] = useState(new Date()); - const [endValue, setEndValue] = useState(new Date()); const initialDate = new Date(); - const handleStartDateChange = (newValue: Date | null) => { - setStartValue(newValue); - }; - - const handleEndDateChange = (newValue: Date | null) => { - setEndValue(newValue); - }; - - const handleCityChange = (event: ChangeEvent) => { - setCityValue(event.target.value); - }; - - const handleKeyPress = (event: KeyboardEvent) => { - // TODO: Temp placeholder, contains values needed from search to be passed on. - if (event.key === 'Enter') { - event.preventDefault(); - alert(`${cityValue}, ${startValue}, ${endValue}`); - } - }; - return ( @@ -42,8 +33,7 @@ export default function DashboardSearch(): JSX.Element { id="city" label="Search by city" variant="outlined" - onKeyPress={handleKeyPress} - onChange={handleCityChange} + onChange={handleSearchChange} InputProps={{ startAdornment: ( diff --git a/server/controllers/profile.js b/server/controllers/profile.js index b6b029c..8df5565 100644 --- a/server/controllers/profile.js +++ b/server/controllers/profile.js @@ -5,45 +5,59 @@ const asyncHandler = require("express-async-handler"); // @desc Create new profile // @access Public exports.createProfile = asyncHandler(async (req, res, next) => { + const { + firstName, + lastName, + gender, + birthday, + email, + phoneNumber, + location, + profilePic, + description, + availability, + } = req.body; - const { - firstName, - lastName, - gender, - birthday, - email, - phoneNumber, - location, - profilePic, - description, - availability, - } = req.body; - - const profile = await Profile.create({ - firstName, - lastName, - gender, - birthday, - email, - phoneNumber, - location, - profilePic, - description, - availability, - }); + const profile = await Profile.create({ + firstName, + lastName, + gender, + birthday, + email, + phoneNumber, + location, + profilePic, + description, + availability, + }); - res.status(201).json({ - profile, - }); + res.status(201).json({ + profile, + }); }); // @route PUT /profile // @desc updates a profile with given ID // @access Private exports.updateProfile = asyncHandler(async (req, res, next) => { - const id = req.user._id; + const id = req.user._id; - const { + const { + firstName, + lastName, + gender, + birthday, + email, + phoneNumber, + location, + profilePic, + description, + availability, + } = req.body; + + const profile = await Profile.findOneAndUpdate( + { user: id }, + { firstName, lastName, gender, @@ -54,59 +68,54 @@ exports.updateProfile = asyncHandler(async (req, res, next) => { profilePic, description, availability, - } = req.body; - - const profile = await Profile.findOneAndUpdate( - { user: id }, - { - firstName, - lastName, - gender, - birthday, - email, - phoneNumber, - location, - profilePic, - description, - availability, - }, - { new: true } - ); + }, + { new: true } + ); - res.status(200).json({ - profile, - }); + res.status(200).json({ + profile, + }); }); // @route GET /profile // @desc gets a profile with the given ID // @access Private exports.getProfile = asyncHandler(async (req, res, next) => { - const id = req.user._id; - const profile = await Profile.findOne({ user: id }); + const id = req.user._id; + const profile = await Profile.findOne({ user: id }); - if (!profile) { - res.status(404); - throw new Error("The profile does not exist"); - } + if (!profile) { + res.status(404); + throw new Error("The profile does not exist"); + } - res.status(200).json({ - profile, - }); + res.status(200).json({ + profile, + }); }); // @route GET /profiles // @desc gets all profiles // @access Private exports.getAllProfiles = asyncHandler(async (req, res, next) => { - const profiles = await Profile.find(); + const { search, start, end } = req.query; - if (!profiles) { - res.status(500); - throw new Error("0 results"); - } + if (!search || !start || !end) { + const profiles = await Profile.find({ + location: { $regex: search, $options: "i" }, + isSitter: true, + }); + //TODO: Need to check dates to be valid res.status(200).json({ profiles, }); -}); \ No newline at end of file + return; + } + + const profiles = await Profile.find(); + + res.status(200).json({ + profiles, + }); +});