Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
E
exam_11_front
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zarina
exam_11_front
Commits
611c28ab
Commit
611c28ab
authored
Jul 30, 2020
by
zarina
🌊
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
#3
, реализовала возможность добавления товаров
parent
50b7e654
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
298 additions
and
31 deletions
+298
-31
App.test.js
src/App.test.js
+1
-1
UserMenu.js
src/components/UI/Toolbar/Menus/UserMenu.js
+23
-22
AddProductForm.js
src/containers/AddProductForm/AddProductForm.js
+149
-0
App.js
src/containers/App.js
+6
-4
index.js
src/index.js
+1
-1
actionTypes.js
src/store/actionTypes.js
+3
-1
categoriesActions.js
src/store/actions/categoriesActions.js
+19
-0
productsActions.js
src/store/actions/productsActions.js
+92
-0
configureStore.js
src/store/configureStore.js
+4
-2
No files found.
src/App.test.js
View file @
611c28ab
import
React
from
'react'
;
import
{
render
}
from
'@testing-library/react'
;
import
App
from
'./App'
;
import
App
from
'./
containers/
App'
;
test
(
'renders learn react link'
,
()
=>
{
const
{
getByText
}
=
render
(
<
App
/>
);
...
...
src/components/UI/Toolbar/Menus/UserMenu.js
View file @
611c28ab
...
...
@@ -3,27 +3,28 @@ import {DropdownItem, DropdownMenu, DropdownToggle, NavItem, NavLink, Uncontroll
import
{
NavLink
as
RouterNavLink
}
from
"react-router-dom"
;
const
UserMenu
=
({
user
,
logout
})
=>
{
return
(
<
UncontrolledDropdown
nav
inNavbar
>
<
DropdownToggle
nav
caret
>
Hello
,
{
user
.
displayName
}
!
<
/DropdownToggle
>
return
(
<>
<
NavItem
>
<
NavLink
tag
=
{
RouterNavLink
}
to
=
"/products
"
exact
>
<
NavLink
tag
=
{
RouterNavLink
}
to
=
"/
"
exact
>
Products
<
/NavLink
>
<
/NavItem
>
<
DropdownMenu
right
>
<
DropdownItem
>
<
NavItem
>
<
NavLink
tag
=
{
RouterNavLink
}
to
=
"/products/new"
exact
>
Create
product
<
/NavLink
>
<
/DropdownItem
>
<
DropdownItem
divider
/>
<
/NavItem
>
<
UncontrolledDropdown
className
=
'ml-5'
nav
navbar
inNavbar
>
<
DropdownToggle
nav
caret
>
Hello
,
{
user
.
displayName
}
!
<
/DropdownToggle
>
<
DropdownMenu
right
>
<
DropdownItem
divider
/>
<
DropdownItem
onClick
=
{
logout
}
>
Logout
<
/DropdownItem
>
<
/DropdownMenu
>
<
/UncontrolledDropdown
>
)};
<
/UncontrolledDropdown> </
>
)
};
export
default
UserMenu
;
src/containers/AddProductForm/AddProductForm.js
0 → 100644
View file @
611c28ab
import
React
,
{
Component
}
from
"react"
;
import
{
Button
,
Col
,
Form
,
FormGroup
,
Input
,
Label
}
from
"reactstrap"
;
import
{
connect
}
from
"react-redux"
;
import
{
history
}
from
"../../store/configureStore"
;
import
FormElement
from
"../../components/UI/FormElement/FormElement"
;
import
{
createProduct
}
from
"../../store/actions/productsActions"
;
import
{
fetchCategories
}
from
"../../store/actions/categoriesActions"
;
class
AddProduct
extends
Component
{
state
=
{
title
:
""
,
description
:
""
,
image
:
""
,
category
:
""
,
price
:
'1'
};
componentDidMount
()
{
if
(
!
this
.
props
.
user
)
{
history
.
push
(
'/login'
)
}
this
.
props
.
fetchCategories
()
}
componentDidUpdate
()
{
if
(
this
.
state
.
category
===
''
)
{
this
.
setState
({
category
:
this
.
props
.
categories
[
0
].
_id
})
}
}
submitFormHandler
=
(
e
)
=>
{
const
formData
=
new
FormData
();
Object
.
keys
(
this
.
state
).
forEach
(
key
=>
{
formData
.
append
(
key
,
this
.
state
[
key
]);
});
e
.
preventDefault
();
this
.
props
.
onProductCreated
(
formData
)
};
inputChangeHandler
=
(
e
)
=>
{
this
.
setState
({[
e
.
target
.
name
]:
e
.
target
.
value
});
};
fileChangeHandler
=
(
e
)
=>
{
this
.
setState
({
image
:
e
.
target
.
files
[
0
]});
};
getIdByName
=
name
=>
{
for
(
let
i
=
0
;
i
<
this
.
props
.
categories
.
length
;
i
++
)
{
if
(
name
===
this
.
props
.
categories
[
i
].
title
){
return
this
.
props
.
categories
[
i
].
_id
;
}
}
return
name
};
selectChangeHandler
=
e
=>
{
this
.
setState
({
category
:
this
.
getIdByName
(
e
.
target
.
value
)})
};
getFieldError
=
fieldName
=>
{
return
this
.
props
.
error
&&
this
.
props
.
error
.
errors
&&
this
.
props
.
error
.
errors
[
fieldName
]
&&
this
.
props
.
error
.
errors
[
fieldName
].
message
;
};
render
()
{
return
(
<
Form
onSubmit
=
{
this
.
submitFormHandler
}
>
<
FormElement
propertyName
=
"title"
label
=
"Title"
onChange
=
{
this
.
inputChangeHandler
}
value
=
{
this
.
state
.
title
}
required
=
{
true
}
type
=
"text"
placeholder
=
"Enter post title"
error
=
{
this
.
getFieldError
(
"title"
)}
/
>
<
FormElement
propertyName
=
"description"
label
=
"Description"
onChange
=
{
this
.
inputChangeHandler
}
value
=
{
this
.
state
.
description
}
required
=
{
true
}
type
=
"text"
placeholder
=
"Enter post description"
error
=
{
this
.
getFieldError
(
"description"
)}
/
>
<
FormElement
propertyName
=
"image"
label
=
"Image"
onChange
=
{
this
.
fileChangeHandler
}
required
=
{
true
}
type
=
"file"
error
=
{
this
.
getFieldError
(
"image"
)}
/
>
<
FormElement
propertyName
=
"price"
label
=
"Price"
onChange
=
{
this
.
inputChangeHandler
}
value
=
{
this
.
state
.
price
}
required
=
{
true
}
min
=
'1'
type
=
"number"
error
=
{
this
.
getFieldError
(
"price"
)}
/
>
<
FormGroup
row
>
<
Label
sm
=
{
2
}
for
=
"category"
>
Category
<
/Label
>
<
Col
sm
=
{
10
}
>
<
Input
onChange
=
{
this
.
selectChangeHandler
}
type
=
"select"
required
name
=
"category"
id
=
"category"
>
{
this
.
props
.
categories
.
map
(
category
=>
{
return
(
<
option
name
=
{
category
.
_id
}
key
=
{
category
.
_id
}
>
{
category
.
title
}
<
/option>
)
})}
<
/Input
>
<
/Col
>
<
/FormGroup
>
<
FormGroup
row
>
<
Col
sm
=
{{
offset
:
2
,
size
:
10
}}
>
<
Button
type
=
"submit"
>
Publish
Post
<
/Button
>
<
/Col
>
<
/FormGroup
>
<
/Form
>
);
}
}
const
mapStateToProps
=
state
=>
{
return
{
user
:
state
.
users
.
user
,
categories
:
state
.
categories
.
categories
,
error
:
state
.
products
.
error
}
};
const
mapDispatchToProps
=
dispatch
=>
{
return
{
onProductCreated
:
(
product
)
=>
dispatch
(
createProduct
(
product
)),
fetchCategories
:
()
=>
dispatch
(
fetchCategories
())
};
};
export
default
connect
(
mapStateToProps
,
mapDispatchToProps
)(
AddProduct
);
src/App.js
→
src/
containers/
App.js
View file @
611c28ab
import
React
,
{
Component
,
Fragment
}
from
'react'
;
import
Toolbar
from
"./components/UI/Toolbar/Toolbar"
;
import
Toolbar
from
".
.
/components/UI/Toolbar/Toolbar"
;
import
{
Container
}
from
"reactstrap"
;
import
{
Route
,
Switch
,
withRouter
}
from
"react-router-dom"
;
import
Register
from
"./
containers/
Register/Register"
;
import
Login
from
"./
containers/
Login/Login"
;
import
Register
from
"./Register/Register"
;
import
Login
from
"./Login/Login"
;
import
{
connect
}
from
"react-redux"
;
import
{
NotificationContainer
}
from
"react-notifications"
;
import
{
logoutUser
}
from
"./store/actions/usersActions"
;
import
{
logoutUser
}
from
"../store/actions/usersActions"
;
import
AddProductForm
from
"./AddProductForm/AddProductForm"
;
class
App
extends
Component
{
render
()
{
...
...
@@ -24,6 +25,7 @@ class App extends Component {
<
Switch
>
<
Route
path
=
"/register"
exact
component
=
{
Register
}
/
>
<
Route
path
=
"/login"
exact
component
=
{
Login
}
/
>
<
Route
path
=
"/products/new"
exact
component
=
{
AddProductForm
}
/
>
<
/Switch
>
<
/Container
>
<
/main
>
...
...
src/index.js
View file @
611c28ab
...
...
@@ -4,7 +4,7 @@ import {Provider} from 'react-redux';
import
*
as
serviceWorker
from
'./serviceWorker'
;
import
"react-notifications/lib/notifications.css"
import
'bootstrap/dist/css/bootstrap.min.css'
;
import
App
from
'./App'
;
import
App
from
'./
containers/
App'
;
import
{
store
,
history
}
from
"./store/configureStore"
;
import
{
ConnectedRouter
}
from
"connected-react-router"
;
...
...
src/store/actionTypes.js
View file @
611c28ab
export
const
FETCH_PRODUCTS_SUCCESS
=
"FETCH_PRODUCTS_SUCCESS"
;
export
const
GET_FULL_PRODUCT_SUCCESS
=
'GET_FULL_PRODUCT_SUCCESS'
;
export
const
FETCH_CATEGORIES_SUCCESS
=
"FETCH_CATEGORIES_SUCCESS"
;
export
const
REGISTER_USER_SUCCESS
=
"REGISTER_USER_SUCCESS"
;
export
const
REGISTER_USER_FAILURE
=
"REGISTER_USER_FAILURE"
;
export
const
LOGIN_USER_SUCCESS
=
"LOGIN_USER_SUCCESS"
;
...
...
src/store/actions/categoriesActions.js
0 → 100644
View file @
611c28ab
import
{
FETCH_CATEGORIES_SUCCESS
,
FETCH_ERROR
}
from
"../actionTypes"
;
import
axios
from
"../../axios-api"
;
const
fetchCategoriesSuccess
=
(
categories
)
=>
{
return
{
type
:
FETCH_CATEGORIES_SUCCESS
,
categories
};
};
const
fetchError
=
error
=>
{
return
{
type
:
FETCH_ERROR
,
error
};
};
export
const
fetchCategories
=
()
=>
{
return
dispatch
=>
{
axios
.
get
(
"/categories"
).
then
(
response
=>
{
dispatch
(
fetchCategoriesSuccess
(
response
.
data
));
}).
catch
(
e
=>
{
dispatch
(
fetchError
(
e
));
})
};
};
src/store/actions/productsActions.js
0 → 100644
View file @
611c28ab
import
{
FETCH_ERROR
,
FETCH_PRODUCTS_SUCCESS
,
GET_FULL_PRODUCT_SUCCESS
}
from
"../actionTypes"
;
import
axios
from
"../../axios-api"
;
import
{
push
}
from
"connected-react-router"
;
import
{
NotificationManager
}
from
"react-notifications"
;
const
fetchProductsSuccess
=
products
=>
{
return
{
type
:
FETCH_PRODUCTS_SUCCESS
,
products
}
};
const
getFullProductSuccess
=
product
=>
{
return
{
type
:
GET_FULL_PRODUCT_SUCCESS
,
product
:
product
}
};
const
fetchError
=
error
=>
{
return
{
type
:
FETCH_ERROR
,
error
};
};
export
const
fetchProducts
=
(
category
)
=>
{
return
dispatch
=>
{
if
(
category
)
{
axios
.
get
(
'/products?category='
+
category
)
.
then
(
res
=>
{
dispatch
(
fetchProductsSuccess
(
res
.
data
));
})
.
catch
(
e
=>
{
dispatch
(
fetchError
(
e
));
})
}
else
{
axios
.
get
(
'/products'
)
.
then
(
res
=>
{
dispatch
(
fetchProductsSuccess
(
res
.
data
));
})
.
catch
(
e
=>
{
dispatch
(
fetchError
(
e
));
})
}
};
};
export
const
getFullProduct
=
id
=>
{
return
dispatch
=>
{
axios
.
get
(
'/products/'
+
id
)
.
then
(
res
=>
{
dispatch
(
getFullProductSuccess
(
res
.
data
));
})
.
catch
(
e
=>
{
dispatch
(
fetchError
(
e
));
})
};
};
export
const
createProduct
=
product
=>
{
return
(
dispatch
,
getState
)
=>
{
const
token
=
getState
().
users
.
user
.
token
;
const
headers
=
{
Token
:
token
};
console
.
log
(
product
)
return
axios
.
post
(
"/products"
,
product
,
{
headers
})
.
then
(()
=>
{
dispatch
(
push
(
'/'
));
NotificationManager
.
success
(
"Created!"
);
})
.
catch
(
e
=>
{
dispatch
(
fetchError
(
e
));
})
};
};
export
const
deleteProduct
=
id
=>
{
return
(
dispatch
,
getState
)
=>
{
const
token
=
getState
().
users
.
user
.
token
;
const
headers
=
{
Token
:
token
};
console
.
log
(
headers
)
axios
.
delete
(
'/products/'
+
id
,
{
headers
})
.
then
(()
=>
{
dispatch
(
push
(
'/'
));
NotificationManager
.
success
(
"Deleted!"
);
})
.
catch
(
e
=>
{
dispatch
(
fetchError
(
e
));
})
};
};
src/store/configureStore.js
View file @
611c28ab
...
...
@@ -4,15 +4,18 @@ import {connectRouter, routerMiddleware} from "connected-react-router";
import
{
loadFromLocalStorage
,
saveToLocalStorage
}
from
"./localStorage"
;
import
{
applyMiddleware
,
combineReducers
,
compose
,
createStore
}
from
"redux"
;
import
thunkMiddleware
from
'redux-thunk'
;
import
categoriesReducer
from
"./reducers/categoriesReducer"
;
import
usersReducer
from
"./reducers/usersReducer"
;
import
productsReducer
from
"./reducers/productsReducer"
;
const
composeEnhancers
=
window
.
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
||
compose
;
export
const
history
=
createBrowserHistory
();
const
rootReducer
=
combineReducers
({
products
:
productsReducer
,
users
:
usersReducer
,
categories
:
categoriesReducer
,
router
:
connectRouter
(
history
)
});
...
...
@@ -32,4 +35,3 @@ store.subscribe(() => {
}
})
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment