Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added required changes #5

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/features/photos/create/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useState } from 'react';

import { useDispatch } from 'react-redux';
import { addPhoto } from '../photos.slice';
// Task 2: Import the `useDispatch()` method from the appropriate package
// Task 3: Import the `addPhoto()` action creator from the photos slice

Expand All @@ -8,6 +9,7 @@ import './create.css';
export default function CreatePhoto() {
const [formData, setFormData] = useState({ imageUrl: '', caption: '' });
// Task 4: Store a reference to the Redux store's dispatch method in a variable called `dispatch`
const dispatch = useDispatch();

function handleChange({ target: { name, value } }) {
setFormData({
Expand All @@ -19,6 +21,7 @@ export default function CreatePhoto() {
function handleSubmit(event) {
event.preventDefault();
// Task 5: Dispatch the `addPhoto()` action creator, passing in the form data
dispatch(addPhoto({imageUrl:formData.imageUrl, caption:formData.caption}));
setFormData({ imageUrl: '', caption: '' });
}

Expand Down Expand Up @@ -50,4 +53,4 @@ export default function CreatePhoto() {
<input type="submit" />
</form>
);
}
}
8 changes: 6 additions & 2 deletions src/features/photos/list/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import { useSelector, useDispatch } from 'react-redux';
import {
// Task 7: Import the `removePhoto()` action creator from the photos slice
removePhoto,
selectAllPhotos,
// Task 13: Import the `selectFilteredPhotos()` selector from the photos slice
selectFilteredPhotos,
} from '../photos.slice';
import './list.css';

export default function PhotosList() {
// Task 14: Call `useSelector()` below with `selectFilteredPhotos` instead of `selectAllPhotos`
const photos = useSelector(selectAllPhotos);
const photos = useSelector(selectFilteredPhotos);
// Task 8: Store a reference to the Redux store's dispatch method in a variable called `dispatch`
const dispatch = useDispatch();

function handleDeleteButtonClick(id) {
// Task 9: Dispatch the `removePhoto()` action creator, passing in the id
dispatch(removePhoto(id));
}

const photosListItems = photos.map(({ id, caption, imageUrl }) => (
Expand All @@ -34,4 +38,4 @@ export default function PhotosList() {
) : (
<h3>No doggies to display...</h3>
);
}
}
17 changes: 16 additions & 1 deletion src/features/photos/photos.slice.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,19 @@ const options = {
// Task 1: Create an `addPhoto()` case reducer that adds a photo to state.photos.
// Task 1 Hint: You can use state.photos.unshift()
// `unshift()` documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift
addPhoto: (state, action) => {
state.photos.unshift({ id: state.photos.length + 1, caption: action.payload.caption, imageUrl: action.payload.imageUrl });
},

// Task 6: Create an `removePhoto()` case reducer that removes a photo from state.photos
// Task 6 Hint: You can use state.photos.splice()
// `splice()` documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
removePhoto: (state, action) => {
state.photos.splice(
state.photos.findIndex((photo) => photo.id === action.payload),
1
);
}
},
};

Expand All @@ -29,4 +38,10 @@ export default photosSlice.reducer;
export const selectAllPhotos = (state) => state.photos.photos;
export const selectFilteredPhotos = (state) => {
// Task 12: Complete `selectFilteredPhotos()` selector to return a filtered list of photos whose captions match the user's search term
};
const photos = selectAllPhotos(state);
const searchTerm = selectSearchTerm(state);

return photos.filter((photo) =>
photo.caption.toLowerCase().includes(searchTerm.toLowerCase())
);
};
4 changes: 3 additions & 1 deletion src/features/search/search-bar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import './search-bar.css';
export default function SearchBar() {
const searchTerm = useSelector(selectSearchTerm);
// Task 10: Store a reference to the Redux store's dispatch method in a variable called `dispatch`
const dispatch = useDispatch();

function handleChange({ target: { value } }) {
// Task 11: Dispatch the `setSearchTerm()` action creator, passing in the value of the search input
dispatch(setSearchTerm(value));
}

return (
Expand All @@ -23,4 +25,4 @@ export default function SearchBar() {
/>
</form>
);
}
}
9 changes: 6 additions & 3 deletions src/features/suggestion/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ import {
selectError,
selectLoading,
// Task 18: Import the `selectSuggestion()` selector from the suggestion slice
selectSuggestion,
} from './suggestion.slice';
import './suggestion.css';

export default function Suggestion() {
// Task 19: Call useSelector() with the selectSuggestion() selector
// The component needs to access the `imageUrl` and `caption` properties of the suggestion object.
const {imageUrl, caption} = useSelector(selectSuggestion);
const loading = useSelector(selectLoading);
const error = useSelector(selectError);
const dispatch = useDispatch();

useEffect(() => {
async function loadSuggestion() {
// Task 20: Dispatch the fetchSuggestion() action creator
dispatch(fetchSuggestion());
}
loadSuggestion();
}, [dispatch]);
Expand All @@ -31,8 +34,8 @@ export default function Suggestion() {
// Task 21: Enable the two JSX lines below needed to display the suggestion on the page
render = (
<>
{/* <img alt={caption} src={imageUrl} />
<p>{imageUrl}</p> */}
<img alt={caption} src={imageUrl} />
<p>{caption}</p>
</>
);
}
Expand All @@ -43,4 +46,4 @@ export default function Suggestion() {
{render}
</section>
);
}
}
26 changes: 24 additions & 2 deletions src/features/suggestion/suggestion.slice.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';

export const fetchSuggestion =
createAsyncThunk(/* Task 15: Complete the `createAsyncThunk()` function to load a suggestion from this URL: http://localhost:3004/api/suggestion */);
createAsyncThunk(/* Task 15: Complete the `createAsyncThunk()` function to load a suggestion from this URL: http://localhost:3004/api/suggestion */
'suggestion/fetchSuggestion',
async (arg, thunkAPI) => {
const reponse = await fetch('http://localhost:3004/api/suggestion');
const { data } = await reponse.json();
console.log(data);
return data;
}
);

const initialState = {
suggestion: '',
Expand All @@ -15,6 +23,19 @@ const options = {
reducers: {},
extraReducers: {
/* Task 16: Inside `extraReducers`, add reducers to handle all three promise lifecycle states - pending, fulfilled, and rejected - for the `fetchSuggestion()` call */
[fetchSuggestion.pending]: (state) => {
state.loading = true;
state.error = false;
},
[fetchSuggestion.fulfilled]: (state, { payload: { imageUrl, caption} }) => {
state.suggestion = { imageUrl, caption };
state.loading = false;
state.error = false;
},
[fetchSuggestion.rejected]: (state, action) => {
state.loading = false;
state.error = true;
},
},
};

Expand All @@ -23,6 +44,7 @@ const suggestionSlice = createSlice(options);
export default suggestionSlice.reducer;

// Task 17: Create a selector, called `selectSuggestion`, for the `suggestion` state variable and export it from the file
export const selectSuggestion = (state) => state.suggestion.suggestion;

export const selectLoading = (state) => state.suggestion.loading;
export const selectError = (state) => state.suggestion.error;
export const selectError = (state) => state.suggestion.error;