Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
F
Full-Stack
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
1
Merge Requests
1
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
Нұрасыл Қайратұлы
Full-Stack
Commits
4df12fa3
Commit
4df12fa3
authored
Jul 16, 2024
by
Nurasyl
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
закончил
parent
aea3f155
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
158 additions
and
8 deletions
+158
-8
products.json
Backend/src/data/products.json
+14
-0
index.ts
Backend/src/index.ts
+2
-1
product.route.ts
Backend/src/routes/product.route.ts
+1
-1
App.tsx
Frontend/src/App.tsx
+2
-0
ProductForm.tsx
Frontend/src/components/ProductForm/ProductForm.tsx
+92
-0
NewProduct.tsx
Frontend/src/containers/NewProduct/NewProduct.tsx
+30
-0
ProductItem.tsx
Frontend/src/containers/Products/ProductItem.tsx
+9
-1
productsSlice.ts
Frontend/src/features/productsSlice.ts
+7
-4
IProduct.ts
Frontend/src/interfaces/IProduct.ts
+1
-1
No files found.
Backend/src/data/products.json
0 → 100644
View file @
4df12fa3
[
{
"id"
:
"d2d4a838-64d2-45e1-954b-ac4d744d9497"
,
"title"
:
"test"
,
"description"
:
"adsdasdadadsadad"
,
"price"
:
500000
},
{
"id"
:
"279e188c-ac70-4186-b3b1-52b9fd721e07"
,
"title"
:
"asasdasd"
,
"description"
:
"asdaddasad"
,
"price"
:
123123
}
]
\ No newline at end of file
Backend/src/index.ts
View file @
4df12fa3
...
...
@@ -2,10 +2,11 @@ import App from './app';
import
logger
from
'./middlewares/logger'
;
import
{
ArticleRoute
}
from
'./routes/article.route'
;
import
{
ProductRoute
}
from
'./routes/product.route'
;
import
cors
from
'cors'
;
const
app
=
new
App
({
port
:
8000
,
middlewares
:
[
logger
()],
middlewares
:
[
logger
()
,
cors
()
],
controllers
:
[
new
ArticleRoute
(),
new
ProductRoute
()],
});
...
...
Backend/src/routes/product.route.ts
View file @
4df12fa3
...
...
@@ -3,7 +3,7 @@ import { IRoute } from "@/interfaces/IRoute.interface";
import
{
ProductController
}
from
"@/controllers/product.controller"
;
export
class
ProductRoute
implements
IRoute
{
public
path
=
'/product'
;
public
path
=
'/product
s
'
;
public
router
=
Router
();
private
controller
:
ProductController
;
...
...
Frontend/src/App.tsx
View file @
4df12fa3
...
...
@@ -2,6 +2,7 @@ import { Container, CssBaseline } from '@mui/material';
import
{
Route
,
Routes
}
from
'react-router-dom'
;
import
{
AppToolbar
}
from
'./components/UI/AppToolbar/AppToolbar'
;
import
{
Products
}
from
'./containers/Products/Products'
;
import
NewProduct
from
'./containers/NewProduct/NewProduct'
;
function
App
()
{
return
(
...
...
@@ -16,6 +17,7 @@ function App() {
<
Container
maxWidth=
"xl"
sx=
{
{
mt
:
10
}
}
>
<
Routes
>
<
Route
path=
"/"
element=
{
<
Products
/>
}
/>
<
Route
path=
"/products/new"
element=
{
<
NewProduct
/>
}
/>
</
Routes
>
</
Container
>
</
main
>
...
...
Frontend/src/components/ProductForm/ProductForm.tsx
0 → 100644
View file @
4df12fa3
import
{
useState
,
ChangeEvent
,
FormEvent
}
from
'react'
;
import
{
Box
,
Button
,
Grid
,
TextField
}
from
'@mui/material'
;
import
{
ProductData
}
from
'@/containers/NewProduct/NewProduct'
;
interface
State
{
title
:
string
;
price
:
string
;
description
:
string
;
}
interface
Props
{
onSubmit
:
(
data
:
ProductData
)
=>
void
;
}
const
ProductForm
=
({
onSubmit
}:
Props
)
=>
{
const
[
state
,
setState
]
=
useState
<
State
>
({
title
:
''
,
price
:
''
,
description
:
''
,
});
const
submitFormHandler
=
(
e
:
FormEvent
<
HTMLFormElement
>
)
=>
{
e
.
preventDefault
();
const
newProduct
:
ProductData
=
{
title
:
state
.
title
,
description
:
state
.
description
,
price
:
parseInt
(
state
.
price
),
}
onSubmit
(
newProduct
)
};
const
inputChangeHandler
=
(
e
:
ChangeEvent
<
HTMLInputElement
>
)
=>
{
const
{
name
,
value
}
=
e
.
target
;
setState
((
prevState
)
=>
{
return
{
...
prevState
,
[
name
]:
value
};
});
};
return
(
<
Box
component=
{
'form'
}
autoComplete=
"off"
onSubmit=
{
submitFormHandler
}
paddingY=
{
2
}
>
<
Grid
container
direction=
"column"
spacing=
{
2
}
>
<
Grid
item
xs
>
<
TextField
fullWidth
variant=
"outlined"
id=
"title"
label=
"Title"
value=
{
state
.
title
}
onChange=
{
inputChangeHandler
}
name=
"title"
/>
</
Grid
>
<
Grid
item
xs
>
<
TextField
fullWidth
variant=
"outlined"
id=
"price"
label=
"Price"
value=
{
state
.
price
}
onChange=
{
inputChangeHandler
}
name=
"price"
/>
</
Grid
>
<
Grid
item
xs
>
<
TextField
fullWidth
multiline
rows=
{
3
}
variant=
"outlined"
id=
"description"
label=
"Description"
value=
{
state
.
description
}
onChange=
{
inputChangeHandler
}
name=
"description"
/>
</
Grid
>
<
Grid
item
xs
>
<
Button
type=
"submit"
color=
"primary"
variant=
"contained"
>
Create
</
Button
>
</
Grid
>
</
Grid
>
</
Box
>
);
};
export
default
ProductForm
;
Frontend/src/containers/NewProduct/NewProduct.tsx
0 → 100644
View file @
4df12fa3
import
{
Typography
}
from
'@mui/material'
;
import
ProductForm
from
'../../components/ProductForm/ProductForm'
;
import
{
useNavigate
}
from
'react-router-dom'
;
import
{
createProduct
}
from
'../../features/productsSlice'
;
import
{
useAppDispatch
}
from
'../../store'
;
export
interface
ProductData
{
title
:
string
;
description
:
string
;
price
:
number
;
}
const
NewProduct
=
()
=>
{
const
dispatch
=
useAppDispatch
();
const
navigate
=
useNavigate
();
const
onProductFormSubmit
=
async
(
productData
:
ProductData
)
=>
{
await
dispatch
(
createProduct
(
productData
));
navigate
(
'/'
);
};
return
(
<>
<
Typography
variant=
"h4"
>
New product
</
Typography
>
<
ProductForm
onSubmit=
{
onProductFormSubmit
}
/>
</>
);
};
export
default
NewProduct
;
Frontend/src/containers/Products/ProductItem.tsx
View file @
4df12fa3
import
{
Link
}
from
'react-router-dom'
;
import
{
Grid
,
Card
,
CardHeader
,
CardContent
,
CardActions
,
IconButton
,
Typography
}
from
'@mui/material'
;
import
{
Grid
,
Card
,
CardHeader
,
CardContent
,
CardActions
,
IconButton
,
Typography
,
}
from
'@mui/material'
;
import
{
ArrowForward
}
from
'@mui/icons-material'
;
import
{
IProduct
}
from
'@/interfaces/IProduct'
;
...
...
Frontend/src/features/productsSlice.ts
View file @
4df12fa3
import
{
axiosApiClient
}
from
"../helpers/axiosApiClient"
;
import
{
IProduct
}
from
"../interfaces/IProduct"
;
import
{
createAsyncThunk
,
createSlice
}
from
"@reduxjs/toolkit"
;
import
{
axiosApiClient
}
from
'../helpers/axiosApiClient'
;
import
{
IProduct
}
from
'../interfaces/IProduct'
;
import
{
createAsyncThunk
,
createSlice
}
from
'@reduxjs/toolkit'
;
interface
State
{
products
:
IProduct
[];
...
...
@@ -19,6 +18,10 @@ export const fetchProducts = createAsyncThunk('fetch/products', async () => {
return
await
axiosApiClient
.
get
<
IProduct
[]
>
(
'/products'
).
then
((
res
)
=>
res
.
data
);
});
export
const
createProduct
=
createAsyncThunk
(
'create/products'
,
async
(
payload
:
IProduct
)
=>
{
return
await
axiosApiClient
.
post
<
IProduct
>
(
'/products'
,
payload
).
then
((
res
)
=>
res
.
data
);
});
const
productsSlice
=
createSlice
({
name
:
'products'
,
initialState
,
...
...
Frontend/src/interfaces/IProduct.ts
View file @
4df12fa3
export
interface
IProduct
{
id
:
string
;
id
?
:
string
;
title
:
string
;
description
:
string
;
price
:
number
;
...
...
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