diff --git a/src/components/App.tsx b/src/components/App.tsx
index e8c7d74..31470ce 100644
--- a/src/components/App.tsx
+++ b/src/components/App.tsx
@@ -1,21 +1,28 @@
import React, { FC } from 'react'
import styled from '@emotion/styled'
import Header from './Header'
+import Favourites from './Favourites'
+import Main from "./Main"
const App: FC = () => {
return (
- {/* Happy coding! */}
+
+
)
}
const Container = styled.div({
margin: '0 auto',
- height: '100%',
width: '560px',
paddingTop: '60px',
+ paddingBottom:'20px',
+ "@media (max-width: 500px)": {
+ width:'100%',
+ padding:'60px 10px 0'
+ },
})
-export default App
+export default App
\ No newline at end of file
diff --git a/src/components/Favouriates.tsx b/src/components/Favouriates.tsx
new file mode 100644
index 0000000..e5e1cc2
--- /dev/null
+++ b/src/components/Favouriates.tsx
@@ -0,0 +1,61 @@
+import React from 'react'
+import styled from '@emotion/styled'
+import { RootStateOrAny, useDispatch, useSelector } from 'react-redux'
+import Heart from './Heart'
+import DogImage from './dogImage'
+import { favoriteFunc } from '../redux/actions'
+
+export default function Favourites() {
+ const favlist: string[] = useSelector((state: RootStateOrAny) => state.favorites)
+ const dispatch = useDispatch()
+
+ const removefavorite = (url: string) => {
+ dispatch(favoriteFunc(url))
+ }
+
+ return (
+ <>
+
+
+ Favorites
+
+ {favlist.length === 0 ? (
+ No dogs in favorites.
+ ) : (
+
+ {favlist.map((item, index) => {
+ return (
+ removefavorite(item)} icon={'redHeartIcon'} />
+ )
+ })}
+
+ )}
+ >
+ )
+}
+
+const HeadingContain = styled.div({
+ display: 'flex',
+ marginTop: '48px',
+})
+
+
+
+const Heading = styled.h1({
+ fontWeight: 'bold',
+ fontSize: '24px',
+ lineHeight: '33px',
+ marginLeft: '20px',
+})
+
+const Result = styled.div({
+ margin: '44px auto 0',
+ width: '100%',
+ display: 'grid',
+ gap: '30px',
+ gridTemplateColumns: 'repeat(3, 1fr)',
+})
+
+const Msg = styled.div({
+ marginTop:"20px"
+})
diff --git a/src/components/Heart.tsx b/src/components/Heart.tsx
index 2431e55..5bde811 100644
--- a/src/components/Heart.tsx
+++ b/src/components/Heart.tsx
@@ -1,20 +1,17 @@
-import React, { FC } from 'react'
-import styled from '@emotion/styled'
-import { icons } from '../assets'
-
interface Props {
icon: string
alt: string
+ onClick?:React.MouseEventHandler
}
-const Heart: FC = ({ icon, alt }) => {
- return
+const Heart: FC = ({ icon, alt,onClick }) => {
+ return
}
const HeartIcon = styled.img({
width: '17px',
height: '15px',
alignSelf: 'center',
+ cursor:"pointer"
})
-
export default Heart
diff --git a/src/components/Inputbox.tsx b/src/components/Inputbox.tsx
new file mode 100644
index 0000000..ca019a8
--- /dev/null
+++ b/src/components/Inputbox.tsx
@@ -0,0 +1,61 @@
+import styled from '@emotion/styled'
+import React from 'react'
+import { icons } from '../assets/icons'
+
+type PropsTypes ={
+ onSubmit:React.FormEventHandler
+ onChange:React.ChangeEventHandler
+ value:string
+}
+
+function Inputbox({onSubmit,value, onChange}:PropsTypes) {
+ return (
+
+ )
+}
+const Form = styled.form({
+ margin: '48px auto',
+ width: '100%',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderRadius: '4px',
+ border: 'none',
+})
+
+const Input = styled.input({
+ width: '100%',
+ display: 'block',
+ padding: '8px 17px',
+ background: '#F7F7F7',
+ border: 'none',
+ fontFamily: 'Nunito Sans',
+ fontStyle: 'normal',
+ fontWeight: 400,
+ fontSize: '16px',
+ lineHeight: '22px',
+ color: '#44484C',
+ outline: "none"
+})
+
+const Button = styled.button({
+ alignSelf: 'stretch',
+ padding: '0 16px',
+ background: '#0794E3',
+ border: 'none',
+ color: '#FFFFFF',
+ borderRadius: '4px',
+ display: 'flex',
+ gap: '5px',
+ alignItems: 'center',
+ justifyContent: 'center',
+ cursor: "pointer"
+})
+
+export default Inputbox
diff --git a/src/components/Main.tsx b/src/components/Main.tsx
new file mode 100644
index 0000000..1dce5a7
--- /dev/null
+++ b/src/components/Main.tsx
@@ -0,0 +1,71 @@
+import React, { useState, FormEvent } from 'react'
+import styled from '@emotion/styled'
+import DogImage from './DogImage'
+import { RootStateOrAny, useDispatch, useSelector } from 'react-redux'
+import { favoriteFunc } from '../redux/actions'
+import Inputbox from './Inputbox'
+
+type Maintypes = {
+ message?: string[]
+ status?: string
+}
+
+function Main() {
+ const [search, Setsearch] = useState("")
+ const [doglist, Setdoglist] = useState([])
+ const [err,Seterr]=useState(false)
+ const favlist: string[] = useSelector((state: RootStateOrAny) => state.favorites)
+ const dispatch = useDispatch()
+
+ const handleSubmit = async (e: FormEvent) => {
+ e.preventDefault()
+ const res: Maintypes = await (await fetch(`https://dog.ceo/api/breed/${search}/images/random/10`)).json()
+ if (res.status === "success") {
+ Setdoglist(res.message)
+ }else{
+ Setdoglist([])
+ Seterr(true)
+ }
+ }
+
+ const Favorite = (url: string) => {
+ dispatch(favoriteFunc(url))
+ }
+
+
+ return (
+ <>
+
+ Setsearch(e.target.value)}/>
+ {!doglist.length ?
+ <>
+ {err&&No result found
}
+ >:
+ <>
+
+ {doglist.map((item, index) => {
+ return (
+ Favorite(item)} icon={favlist.includes(item) ? 'redHeartIcon' : 'whiteHeartIcon'} />
+ )
+ })}
+
+
+ >}
+ >
+ )
+}
+
+const Result = styled.div({
+ margin: '48px auto',
+ width: '100%',
+ display: 'grid',
+ gap: '30px',
+ gridTemplateColumns: 'repeat(3,1fr)',
+})
+
+
+const Line = styled.div({
+ borderBottom: '1px solid #DADADA',
+})
+
+export default Main
diff --git a/src/components/dogImage.tsx b/src/components/dogImage.tsx
new file mode 100644
index 0000000..0e12961
--- /dev/null
+++ b/src/components/dogImage.tsx
@@ -0,0 +1,39 @@
+import React from 'react'
+import styled from '@emotion/styled'
+import Heart from './Heart'
+
+
+function DogImage({ src, icon, onClick }) {
+ return (
+
+
+
+
+
+
+ )
+}
+
+
+const Container = styled.div({
+ position: "relative"
+})
+
+const Image = styled.img({
+ width: "160px",
+ height: "160px",
+ objectFit: "cover",
+ borderRadius: "4px",
+ "@media (max-width: 600px)": {
+ width:'130px',
+ height:"130px"
+ },
+})
+
+const Icon = styled.div({
+ position: "absolute",
+ bottom: '10px',
+ right: '10px',
+})
+
+export default DogImage
\ No newline at end of file
diff --git a/src/redux/actions.ts b/src/redux/actions.ts
index e69de29..6e39a93 100644
--- a/src/redux/actions.ts
+++ b/src/redux/actions.ts
@@ -0,0 +1,7 @@
+export const favoriteFunc =(url:string)=>{
+ return {
+ type:"FAVORITE",
+ payload:url
+ }
+ }
+
\ No newline at end of file
diff --git a/src/redux/reducer.ts b/src/redux/reducer.ts
index be51d22..86455db 100644
--- a/src/redux/reducer.ts
+++ b/src/redux/reducer.ts
@@ -1,6 +1,22 @@
-export const reducer = (initialState = {}, action) => {
+import { AnyAction } from 'redux'
+
+interface ReducerState {
+ favorites: string[]
+}
+
+const initialState: ReducerState = {
+ favorites: [],
+}
+
+export const favoriteReducer = (state = initialState, action: AnyAction) => {
switch (action.type) {
+ case 'FAVORITE':
+ if (state.favorites.includes(action.payload)) {
+ return { favorites: [...state.favorites.filter((item) => item !== action.payload)] }
+ } else {
+ return { favorites: [...state.favorites, action.payload] }
+ }
default:
- return initialState
+ return state
}
-}
+}
\ No newline at end of file
diff --git a/src/redux/store.ts b/src/redux/store.ts
index 06536aa..da30d22 100644
--- a/src/redux/store.ts
+++ b/src/redux/store.ts
@@ -1,4 +1,8 @@
import { createStore } from 'redux'
-import { reducer } from './reducer'
-export default createStore(reducer)
+import { favoriteReducer } from './reducer'
+
+const store = createStore(favoriteReducer)
+
+
+export default store
\ No newline at end of file