diff --git a/package-lock.json b/package-lock.json index 4cde930..4121725 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@emotion/styled": "^11.10.6", "@mui/icons-material": "^5.11.11", "@mui/material": "^5.11.13", + "@mui/x-data-grid": "^6.4.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", @@ -19,6 +20,7 @@ "@types/node": "^16.11.68", "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", + "axios": "^1.4.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", @@ -3331,9 +3333,9 @@ } }, "node_modules/@mui/utils": { - "version": "5.11.13", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.13.tgz", - "integrity": "sha512-5ltA58MM9euOuUcnvwFJqpLdEugc9XFsRR8Gt4zZNb31XzMfSKJPR4eumulyhsOTK1rWf7K4D63NKFPfX0AxqA==", + "version": "5.12.3", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.12.3.tgz", + "integrity": "sha512-D/Z4Ub3MRl7HiUccid7sQYclTr24TqUAQFFlxHQF8FR177BrCTQ0JJZom7EqYjZCdXhwnSkOj2ph685MSKNtIA==", "dependencies": { "@babel/runtime": "^7.21.0", "@types/prop-types": "^15.7.5", @@ -3352,6 +3354,31 @@ "react": "^17.0.0 || ^18.0.0" } }, + "node_modules/@mui/x-data-grid": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-6.4.0.tgz", + "integrity": "sha512-rFpjJh4ZTJW3JnjmTsn5B32PMMJtjxTdRZyjn3Re5K/BA/iJQvN1qHO26qoqbo4Vt3b3dbRLThM/Q0N59PL2Fw==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@mui/utils": "^5.12.3", + "clsx": "^1.2.1", + "prop-types": "^15.8.1", + "reselect": "^4.1.8" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@mui/material": "^5.4.1", + "@mui/system": "^5.4.1", + "react": "^17.0.2 || ^18.0.0", + "react-dom": "^17.0.2 || ^18.0.0" + } + }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", @@ -5353,6 +5380,29 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/axobject-query": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", @@ -14348,6 +14398,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -15064,6 +15119,11 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", diff --git a/package.json b/package.json index 538d7a0..0090284 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "@emotion/styled": "^11.10.6", "@mui/icons-material": "^5.11.11", "@mui/material": "^5.11.13", + "@mui/x-data-grid": "^6.4.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", @@ -14,6 +15,7 @@ "@types/node": "^16.11.68", "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", + "axios": "^1.4.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", diff --git a/src/Components/Artamonov/ArtamonovPopup/ArtamonovPopup.scss b/src/Components/Artamonov/ArtamonovPopup/ArtamonovPopup.scss new file mode 100644 index 0000000..bb33ccb --- /dev/null +++ b/src/Components/Artamonov/ArtamonovPopup/ArtamonovPopup.scss @@ -0,0 +1,24 @@ +.artamonov_popup { + width: 100%; + height: 100vh; + display: flex; + justify-content: center; + align-items: center; + + &__content { + background-color: #fff; + padding: 1em; + border-radius: 1em; + min-width: 400px; + + + &__header { + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: .5em; + margin-bottom: .5em; + border-bottom: solid 1px #ccc; + } + } +} diff --git a/src/Components/Artamonov/ArtamonovPopup/ArtamonovPopup.tsx b/src/Components/Artamonov/ArtamonovPopup/ArtamonovPopup.tsx new file mode 100644 index 0000000..c1b762c --- /dev/null +++ b/src/Components/Artamonov/ArtamonovPopup/ArtamonovPopup.tsx @@ -0,0 +1,48 @@ +import { Button, Modal, Typography } from '@mui/material'; +import React from 'react'; +import "./ArtamonovPopup.scss"; + +export type IPopup = { + open: boolean, + onClose: () => void; +} + + +type Props = IPopup & { + children: any, + title: string +} + +const ArtamonovPopup = ({ open, onClose, children, title }: Props) => { + + + return ( onClose()} + > + + + + + {title} + + + + onClose()} + > + Close + + + + + + + {children} + + + + + ) +} +export default ArtamonovPopup; \ No newline at end of file diff --git a/src/Components/Kurgankov/KurgankovPopup/KurgankovPopup.scss b/src/Components/Kurgankov/KurgankovPopup/KurgankovPopup.scss new file mode 100644 index 0000000..8989868 --- /dev/null +++ b/src/Components/Kurgankov/KurgankovPopup/KurgankovPopup.scss @@ -0,0 +1,24 @@ +.kurgankov_popup { + width: 100%; + height: 100vh; + display: flex; + justify-content: center; + align-items: center; + + &__content { + background-color: #fff; + padding: 1em; + border-radius: 1em; + min-width: 400px; + + + &__header { + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: .5em; + margin-bottom: .5em; + border-bottom: solid 1px #ccc; + } + } +} diff --git a/src/Components/Kurgankov/KurgankovPopup/KurgankovPopup.tsx b/src/Components/Kurgankov/KurgankovPopup/KurgankovPopup.tsx new file mode 100644 index 0000000..14153d2 --- /dev/null +++ b/src/Components/Kurgankov/KurgankovPopup/KurgankovPopup.tsx @@ -0,0 +1,49 @@ +import { Button, Modal, Typography } from '@mui/material'; +import React from 'react'; +import "./KurgankovPopup.scss"; + +export type IPopup = { + open: boolean, + onClose: () => void; +} + + +type Props = IPopup & { + children: any, + title: string +} + +const KurgankovPopup = ({ open, onClose, children, title }: Props) => { + + + return ( onClose()} + > + + + + + {title} + + + + onClose()} + > + Close + + + + + + + {children} + + + + + ) +} + +export default KurgankovPopup; \ No newline at end of file diff --git a/src/Pages/Route/RouteComponent.tsx b/src/Pages/Route/RouteComponent.tsx index 7405d05..0dd88c8 100644 --- a/src/Pages/Route/RouteComponent.tsx +++ b/src/Pages/Route/RouteComponent.tsx @@ -35,7 +35,15 @@ import {default as OndyshevClient} from "../StudentPage/OndyshevDmitry/Client/Cl import {default as OndyshevManufacturer} from "../StudentPage/OndyshevDmitry/Manufacturer/Manufacturer"; import {default as OndyshevOrder} from "../StudentPage/OndyshevDmitry/Order/Order"; import {default as OndyshevProduct} from "../StudentPage/OndyshevDmitry/Product/Product"; -import {default as OndyshevPurchase} from "../StudentPage/OndyshevDmitry/Purchase/Purchase"; +import { default as OndyshevPurchase } from "../StudentPage/OndyshevDmitry/Purchase/Purchase"; + +import KurgankovPage from "../StudentPage/Kurgankov/KurgankovPage"; +import { default as KurgankovCategory } from '../StudentPage/Kurgankov/Category/CategoryPage'; +import { default as KurgankovClient } from "../StudentPage/Kurgankov/Client/Client"; +import { default as KurgankovManufacturer } from "../StudentPage/Kurgankov/Manufacture/ManufacturePage"; +import { default as KurgankovOrder } from "../StudentPage/Kurgankov/Order/Order"; +import { default as KurgankovProduct } from "../StudentPage/Kurgankov/Product/Product"; +import { default as KurgankovPurchase } from "../StudentPage/Kurgankov/Purchase/Purchase"; import SimakovMatveyPage from "../StudentPage/SimakovMatvey/SimakovMatveyPage"; import {default as SimakovCategory} from '../StudentPage/SimakovMatvey/Category/CategoryPage'; @@ -93,6 +101,15 @@ import DyakovDanilPage from "../StudentPage/DyakovDanil/DyakovDanilPage"; import { default as DyakovTest2 } from "../StudentPage/DyakovDanil/Test2/Test2"; import { default as DyakovTest1 } from "../StudentPage/DyakovDanil/Test1/Test1"; +import ArtamonovPage from "../StudentPage/Artamonov/ArtamonovPage"; +import { default as ArtamonovCategory } from '../StudentPage/Artamonov/Category/CategoryPage'; +import { default as ArtamonovClient } from "../StudentPage/Artamonov/Client/Client"; +import { default as ArtamonovManufacturer } from "../StudentPage/Artamonov/Manufacture/ManufacturePage"; +import { default as ArtamonovOrder } from "../StudentPage/Artamonov/Order/Order"; +import { default as ArtamonovProduct } from "../StudentPage/Artamonov/Product/Product"; +import { default as ArtamonovPurchase } from "../StudentPage/Artamonov/Purchase/Purchase"; + + const RouteComponent = () => { @@ -118,6 +135,15 @@ const RouteComponent = () => { } /> + }> + } /> + } /> + } /> + } /> + } /> + } /> + + }> } /> } /> @@ -196,6 +222,15 @@ const RouteComponent = () => { } /> + }> + } /> + } /> + } /> + } /> + } /> + } /> + + diff --git a/src/Pages/StudentPage/Artamonov/ArtamonovPage.scss b/src/Pages/StudentPage/Artamonov/ArtamonovPage.scss new file mode 100644 index 0000000..e85c842 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/ArtamonovPage.scss @@ -0,0 +1,4 @@ +.self_page_content { + display:flex; + gap:1em; +} \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/ArtamonovPage.tsx b/src/Pages/StudentPage/Artamonov/ArtamonovPage.tsx new file mode 100644 index 0000000..c25a187 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/ArtamonovPage.tsx @@ -0,0 +1,47 @@ +import React, { useEffect } from 'react'; +import Header from "../../../Components/Header/Header"; +import ContentBlock from "../../../Components/ContentBlock/ContentBlock"; +import AsideMenu from "./AsideMenu/AsideMenu"; +import { Outlet } from "react-router-dom"; +import "./ArtamonovPage.scss"; +import axios from 'axios'; + + +export const artamonovAxios = axios.create({}) + + +const ArtamonovPage = () => { + + const doLogin = () => { + axios.post<{ authToken: string }>('https://canstudy.ru/orderapi/user/login', { + identifier: 'FD76C504-09E1-4514-B023-09DCC874BEE1' + }) + .then(res => { + artamonovAxios + .defaults + .headers + .common['Authorization'] = 'Bearer ' + res.data.authToken + }) + } + + + useEffect(() => { + doLogin(); + }, []) + + return ( + + + + + + + + + + + + ); +}; + +export default ArtamonovPage; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/AsideMenu/AsideMenu.scss b/src/Pages/StudentPage/Artamonov/AsideMenu/AsideMenu.scss new file mode 100644 index 0000000..818ca2b --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/AsideMenu/AsideMenu.scss @@ -0,0 +1,4 @@ +.aside { + width: 15em; + border: 1px solid black; +} \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/AsideMenu/AsideMenu.tsx b/src/Pages/StudentPage/Artamonov/AsideMenu/AsideMenu.tsx new file mode 100644 index 0000000..8e1b765 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/AsideMenu/AsideMenu.tsx @@ -0,0 +1,46 @@ +import { List, ListItem, ListItemButton, ListItemText } from '@mui/material'; +import React from 'react'; +import "./AsideMenu.scss"; +import { useNavigate } from "react-router-dom"; + +const AsideMenu = () => { + + const navigate = useNavigate(); + + return ( + + + + navigate('category')}> + + + + + + navigate('manufacture')}> + + + + + + navigate('client')}> + + + + + + navigate('product')}> + + + + + + navigate('order')}> + + + + + ); +}; + +export default AsideMenu; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Category/CategoryPage.tsx b/src/Pages/StudentPage/Artamonov/Category/CategoryPage.tsx new file mode 100644 index 0000000..9904dbf --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Category/CategoryPage.tsx @@ -0,0 +1,155 @@ +import { Button, IconButton } from '@mui/material'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import React, { useEffect, useState } from 'react'; +import { Category } from './models'; +//import Category from "./models"; +import DeleteIcon from '@mui/icons-material/Delete'; +import EditIcon from '@mui/icons-material/Edit'; +import ArtamonovPage, { artamonovAxios } from '../ArtamonovPage'; +import ArtamonovPopup from '../../../../Components/Artamonov/ArtamonovPopup/ArtamonovPopup'; +import CreateCategoryPopup from "./Popups/CreateCategoryPopup"; +import EditCategoryPopup from "./Popups/EditCategoryPopup"; +import axios from 'axios'; + +const CategoryPage = () => { + + const [categoryList, setCategoryList] = useState([]) + + const getCategories = () => { + artamonovAxios.get<{ items: Category[] }>('https://canstudy.ru/orderapi/category/list') + .then(res => { + setCategoryList(res.data.items); + }) + } + + + useEffect(() => { + getCategories(); + }, []) + + + + const onDeleteClick = (id: number) => { + artamonovAxios.delete(`https://canstudy.ru/orderapi/category/${id}`) + .then(res => { + setCategoryList(prev => + prev.filter(el => el.id !== id) + ) + }) + } + + const onEditClick = (id: number) => { + const category = categoryList.find(el => el.id === id)!; + setEditCategory(category) + } + + const onCreate = (category: Category) => { + setCategoryList(prev => [...prev, category]) + } + + const onEdit = (category: Category) => { + setCategoryList(prev => { + const curCategory = prev.find(el => el.id === category.id)!; + + curCategory.name = category.name; + + return [...prev] + }) + } + + const columns: GridColDef[] = [ + { + field: 'id', + headerName: 'Id' + }, + { + field: 'name', + headerName: 'Name', + flex: 1 + }, + { + field: '', + headerName: '', + renderCell: (e: any) => { + return + + onEditClick(e.row.id)} + > + + + + onDeleteClick(e.row.id)} + aria-label="delete" + > + + + + } + } + ] + + const [createPopupOpened, setCreatePopupOpened] = useState(false) + + const [editCategory, setEditCategory] = useState(null) + + return ( + + + {createPopupOpened && setCreatePopupOpened(false)} + onCreate={(newCategory) => onCreate(newCategory)} + />} + + {editCategory !== null && setEditCategory(null)} + category={editCategory} + onEdit={(editCategory) => onEdit(editCategory)} + />} + + + + Категории + + + setCreatePopupOpened(true)} + > + Создать категорию + + + + + + + + + + + ); +}; + +export default CategoryPage; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Category/Popups/CreateCategoryPopup.tsx b/src/Pages/StudentPage/Artamonov/Category/Popups/CreateCategoryPopup.tsx new file mode 100644 index 0000000..27fb830 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Category/Popups/CreateCategoryPopup.tsx @@ -0,0 +1,69 @@ +import React, { useEffect, useState } from 'react'; +import ArtamonovPopup, { IPopup } from "../../../../../Components/Artamonov/ArtamonovPopup/ArtamonovPopup"; +import { Button, TextField } from "@mui/material"; +import { Category } from "../models"; +import axios from 'axios'; +import { artamonovAxios } from '../../ArtamonovPage'; + +type Props = IPopup & { + onCreate: (newCategory: Category) => void; +} + +const CreateCategoryPopup = ({ open, onClose, onCreate }: Props) => { + + const createCategory = () => { + artamonovAxios.post<{ item: Category }>('https://canstudy.ru/orderapi/category', + { + name: categoryName + }) + .then(res => { + onCreate(res.data.item) + }) + } + + + const [categoryName, setCategoryName] = useState('') + + const onCreateClick = () => { + createCategory(); + + onClose(); + } + + return ( + onClose()} + > + + setCategoryName(e.target.value)} + /> + + + onCreateClick()} + > + + + + + + + ); +}; + +export default CreateCategoryPopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Category/Popups/EditCategoryPopup.tsx b/src/Pages/StudentPage/Artamonov/Category/Popups/EditCategoryPopup.tsx new file mode 100644 index 0000000..af167f6 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Category/Popups/EditCategoryPopup.tsx @@ -0,0 +1,69 @@ +import React, { useState } from 'react'; +import ArtamonovPopup, { IPopup } from "../../../../../Components/Artamonov/ArtamonovPopup/ArtamonovPopup"; +import { Button, TextField } from "@mui/material"; +import { Category } from "../models"; +import { artamonovAxios } from "../../ArtamonovPage"; + +type Props = IPopup & { + onEdit: (newCategory: Category) => void; + category: Category +} + +const EditCategoryPopup = ({ open, onClose, category, onEdit }: Props) => { + + const [categoryEdit, setCategoryEdit] = useState(category) + + const onEditClick = () => { + + artamonovAxios.patch<{ item: Category }>('https://canstudy.ru/orderapi/category', + { + item: { + id: category.id, + name: category.name, + } + }) + .then(res => { + onEdit(categoryEdit) + onClose(); + }) + } + + return ( + onClose()} + > + + + setCategoryEdit(prev => ({ ...prev, name: e.target.value })) + } + /> + + + onEditClick()} + > + + + + + + + ); +}; + +export default EditCategoryPopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Category/models.ts b/src/Pages/StudentPage/Artamonov/Category/models.ts new file mode 100644 index 0000000..a893b01 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Category/models.ts @@ -0,0 +1,4 @@ +export type Category = { + id:number, + name:string +} \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Client/Client.tsx b/src/Pages/StudentPage/Artamonov/Client/Client.tsx new file mode 100644 index 0000000..f547adf --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Client/Client.tsx @@ -0,0 +1,186 @@ +import { Button, IconButton } from '@mui/material'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import React, { useEffect, useState } from 'react'; +import { Client } from './models'; +import DeleteIcon from '@mui/icons-material/Delete'; +import EditIcon from '@mui/icons-material/Edit'; +import { artamonovAxios } from '../ArtamonovPage'; +import CreateClientPopup from "./Popups/CreateClientPopup"; +import EditClientPopup from "./Popups/EditClientPopup"; +import MaleIcon from '@mui/icons-material/Male'; +import FemaleIcon from '@mui/icons-material/Female'; + +const ClientPage = () => { + + const [ClientList, setClientList] = useState([]) + + const getClients = () => { + artamonovAxios.get<{ items: Client[] }>('https://canstudy.ru/orderapi/Client/list') + .then(res => { + setClientList(res.data.items); + }) + } + + + useEffect(() => { + getClients(); + }, []) + + + const onDeleteClick = (id: number) => { + artamonovAxios.delete(`https://canstudy.ru/orderapi/Client/${id}`) + .then(res => { + setClientList(prev => + prev.filter(el => el.id !== id) + ) + }) + } + + const onEditClick = (id: number) => { + const Client = ClientList.find(el => el.id === id)!; + setEditClient(Client) + } + + const onCreate = (Client: Client) => { + setClientList(prev => [...prev, Client]) + } + + const onEdit = (Client: Client) => { + setClientList(prev => { + const curClient = prev.find(el => el.id === Client.id)!; + + if (curClient) { + curClient.firstName = Client.firstName; + curClient.lastName = Client.lastName; + curClient.phoneNumber = Client.phoneNumber; + curClient.email = Client.email; + curClient.sex = Client.sex; + } + + return [...prev] + }) + } + + const columns: GridColDef[] = [ + { + field: 'id', + headerName: 'Id' + }, + { + field: 'sex', + headerName: '', + flex: 1, + renderCell: (e) => { + if (e.value?.toString() === "0") + return + + return + } + }, + { + field: 'firstName', + headerName: '', + flex: 1 + }, + { + field: 'lastName', + headerName: '', + flex: 1 + }, + { + field: 'email', + headerName: '', + flex: 1 + }, + { + field: 'phoneNumber', + headerName: '', + flex: 1 + }, + { + field: '', + headerName: '', + renderCell: (e: any) => { + return + + onEditClick(e.row.id)} + > + + + + onDeleteClick(e.row.id)} + aria-label="delete" + > + + + + } + } + ] + + const [createPopupOpened, setCreatePopupOpened] = useState(false) + + const [editClient, setEditClient] = useState(null) + + return ( + + + {createPopupOpened && setCreatePopupOpened(false)} + onCreate={(newClient) => onCreate(newClient)} + />} + + + {editClient !== null && setEditClient(null)} + client={editClient} + onEdit={(editClient) => onEdit(editClient)} + />} + + + + + + + setCreatePopupOpened(true)} + > + + + + + + + + + + + + ); +}; + +export default ClientPage; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Client/Popups/CreateClientPopup.tsx b/src/Pages/StudentPage/Artamonov/Client/Popups/CreateClientPopup.tsx new file mode 100644 index 0000000..90cd311 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Client/Popups/CreateClientPopup.tsx @@ -0,0 +1,116 @@ +import React, { useEffect, useState } from 'react'; +import ArtamonovPopup, { IPopup } from "../../../../../Components/Artamonov/ArtamonovPopup/ArtamonovPopup"; +import { Button, FormControl, InputLabel, MenuItem, Select, TextField } from "@mui/material"; +import { Client } from "../models"; +import axios from 'axios'; +import { artamonovAxios } from '../../ArtamonovPage'; + +type Props = IPopup & { + onCreate: (newClient: Client) => void; +} + +const CreateClientPopup = ({ open, onClose, onCreate }: Props) => { + + const createClient = () => { + artamonovAxios.post<{ item: Client }>('https://canstudy.ru/orderapi/Client', + { + ...client + }) + .then(res => { + onCreate(res.data.item) + }) + } + + + const [client, setClient] = useState({ + sex: 0, + firstName: "", + lastName: "", + email: "", + phoneNumber: "", + id: 0, + }) + + const onCreateClick = () => { + createClient(); + + onClose(); + } + + return ( + onClose()} + > + + + + + setClient(prev => ({ ...prev, sex: e.target.value as any }))} + > + + + + + + + setClient(prev => ({ ...prev, firstName: e.target.value }))} + /> + + setClient(prev => ({ ...prev, lastName: e.target.value }))} + /> + + setClient(prev => ({ ...prev, email: e.target.value }))} + /> + + setClient(prev => ({ ...prev, phoneNumber: e.target.value }))} + /> + + + onCreateClick()} + > + + + + + + + ); +}; + +export default CreateClientPopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Client/Popups/EditClientPopup.tsx b/src/Pages/StudentPage/Artamonov/Client/Popups/EditClientPopup.tsx new file mode 100644 index 0000000..192dc61 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Client/Popups/EditClientPopup.tsx @@ -0,0 +1,104 @@ +import React, { useState } from 'react'; +import ArtamonovPopup, { IPopup } from "../../../../../Components/Artamonov/ArtamonovPopup/ArtamonovPopup"; +import { Button, FormControl, InputLabel, MenuItem, Select, TextField } from "@mui/material"; +import { Client } from "../models"; +import { artamonovAxios } from "../../ArtamonovPage"; + +type Props = IPopup & { + onEdit: (newClient: Client) => void; + client: Client +} + +const EditClientPopup = ({ open, onClose, client: clientEdit, onEdit }: Props) => { + + const [client, setClient] = useState(clientEdit) + + const onEditClick = () => { + + artamonovAxios.patch<{ item: Client }>('https://canstudy.ru/orderapi/Client', + { + item: { + ...client + } + }) + .then(res => { + onEdit(res.data.item) + onClose(); + }) + } + + return ( + onClose()} + > + + + + setClient(prev => ({ ...prev, sex: e.target.value as any }))} + > + + + + + + + setClient(prev => ({ ...prev, firstName: e.target.value }))} + /> + + setClient(prev => ({ ...prev, lastName: e.target.value }))} + /> + + setClient(prev => ({ ...prev, email: e.target.value }))} + /> + + setClient(prev => ({ ...prev, phoneNumber: e.target.value }))} + /> + + + onEditClick()} + > + + + + + + + ); +}; + +export default EditClientPopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Client/models.tsx b/src/Pages/StudentPage/Artamonov/Client/models.tsx new file mode 100644 index 0000000..32338b0 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Client/models.tsx @@ -0,0 +1,8 @@ +export type Client = { + id: number, + sex: number, + firstName: string, + lastName: string, + email: string, + phoneNumber: string +} \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Manufacture/ManufacturePage.tsx b/src/Pages/StudentPage/Artamonov/Manufacture/ManufacturePage.tsx new file mode 100644 index 0000000..ae9164b --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Manufacture/ManufacturePage.tsx @@ -0,0 +1,165 @@ +import { Button, IconButton } from '@mui/material'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import React, { useEffect, useState } from 'react'; +//import manufacture from "./models"; +import DeleteIcon from '@mui/icons-material/Delete'; +import EditIcon from '@mui/icons-material/Edit'; +import { artamonovAxios } from '../ArtamonovPage'; +import { Manufacture } from "./models"; +import CreateManufacturePopup from "./Popups/CreateManufacturePopup"; +import EditManufacturePopup from "./Popups/EditManufacturePopup"; + +const ManufacturePage = () => { + + const [manufactureList, setManufactureList] = useState([]) + + const getManufacturies = () => { + artamonovAxios.get<{ items: Manufacture[] }>('https://canstudy.ru/orderapi/manufacturer/list') + .then(res => { + setManufactureList(res.data.items); + }) + } + + + useEffect(() => { + getManufacturies(); + }, []) + + + const onDeleteClick = (id: number) => { + + artamonovAxios.delete(`https://canstudy.ru/orderapi/manufacturer/${id}`) + .then(res => { + setManufactureList(prev => + prev.filter(el => el.id !== id) + ) + }) + } + + const onEditClick = (id: number) => { + const manufacture = manufactureList.find(el => el.id === id)!; + setEditmanufacture(manufacture) + } + + const onCreate = (manufacture: Manufacture) => { + setManufactureList(prev => [...prev, manufacture]) + } + + const onEdit = (manufacture: Manufacture) => { + setManufactureList(prev => { + const curmanufacture = prev.find(el => el.id === manufacture.id)!; + + curmanufacture.name = manufacture.name; + curmanufacture.country = manufacture.country; + curmanufacture.city = manufacture.city; + + return [...prev] + }) + } + + const columns: GridColDef[] = [ + { + field: 'id', + headerName: 'Id' + }, + { + field: 'name', + headerName: '', + flex: 1 + }, + { + field: 'country', + headerName: '', + flex: 1 + }, + { + field: 'city', + headerName: '', + flex: 1 + }, + { + field: '', + headerName: '', + renderCell: (e: any) => { + return + + onEditClick(e.row.id)} + > + + + + onDeleteClick(e.row.id)} + aria-label="delete" + > + + + + } + } + ] + + const [createPopupOpened, setCreatePopupOpened] = useState(false) + + const [editmanufacture, setEditmanufacture] = useState(null) + + return ( + + + {createPopupOpened && setCreatePopupOpened(false)} + onCreate={(newManufacture) => onCreate(newManufacture)} + />} + + {editmanufacture !== null && setEditmanufacture(null)} + Manufacture={editmanufacture} + onEdit={(editmanufacture) => onEdit(editmanufacture)} + />} + + + + + + + setCreatePopupOpened(true)} + > + + + + + + + + + + + + ); +}; + +export default ManufacturePage; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Manufacture/Popups/CreateManufacturePopup.tsx b/src/Pages/StudentPage/Artamonov/Manufacture/Popups/CreateManufacturePopup.tsx new file mode 100644 index 0000000..9704467 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Manufacture/Popups/CreateManufacturePopup.tsx @@ -0,0 +1,96 @@ +import React, { useState } from 'react'; +import ArtamonovPopup, { IPopup } from "../../../../../Components/Artamonov/ArtamonovPopup/ArtamonovPopup"; +import { Button, TextField } from "@mui/material"; +import { Manufacture } from "../models"; +import { artamonovAxios } from '../../ArtamonovPage'; + +type Props = IPopup & { + onCreate: (newManufacture: Manufacture) => void; +} + +const CreateManufacturePopup = ({ open, onClose, onCreate }: Props) => { + + const createManufacture = () => { + artamonovAxios.post<{ item: Manufacture }>('https://canstudy.ru/orderapi/manufacturer', + { + name: manufacture.name, + city: manufacture.city, + country: manufacture.country + }) + .then(res => { + onCreate(res.data.item) + }) + } + + const [manufacture, setManufacture] = useState({ + id: 0, + name: '', + country: '', + city: '' + }) + + const onCreateClick = () => { + createManufacture(); + + onClose(); + } + + return ( + onClose()} + > + + setManufacture(prev => ( + { ...prev, name: e.target.value } + ))} + /> + + setManufacture(prev => ( + { ...prev, country: e.target.value } + ))} + /> + + setManufacture(prev => ( + { ...prev, city: e.target.value } + ))} + /> + + + onCreateClick()} + > + + + + + + + ); +}; + +export default CreateManufacturePopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Manufacture/Popups/EditManufacturePopup.tsx b/src/Pages/StudentPage/Artamonov/Manufacture/Popups/EditManufacturePopup.tsx new file mode 100644 index 0000000..31b4d18 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Manufacture/Popups/EditManufacturePopup.tsx @@ -0,0 +1,91 @@ +import React, { useState } from 'react'; +import ArtamonovPopup, { IPopup } from "../../../../../Components/Artamonov/ArtamonovPopup/ArtamonovPopup"; +import { Button, TextField } from "@mui/material"; +import { Manufacture } from "../models"; +import { artamonovAxios } from "../../ArtamonovPage"; +import { Category } from "../../Category/models"; + +type Props = IPopup & { + onEdit: (newManufacture: Manufacture) => void; + Manufacture: Manufacture +} + +const EditManufacturePopup = ({ open, onClose, Manufacture, onEdit }: Props) => { + + const [ManufactureEdit, setManufactureEdit] = useState(Manufacture) + + const onEditClick = () => { + artamonovAxios.patch<{ item: Manufacture }>('https://canstudy.ru/orderapi/manufacturer', + { + item: { + id: ManufactureEdit.id, + name: ManufactureEdit.name, + city: ManufactureEdit.city, + country: ManufactureEdit.country, + } + }) + .then(res => { + onEdit(ManufactureEdit) + onClose(); + }) + } + + return ( + onClose()} + > + + + setManufactureEdit(prev => ({ ...prev, name: e.target.value })) + } + /> + + setManufactureEdit(prev => ( + { ...prev, country: e.target.value } + ))} + /> + + setManufactureEdit(prev => ( + { ...prev, city: e.target.value } + ))} + /> + + + onEditClick()} + > + + + + + + + ); +}; + +export default EditManufacturePopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Manufacture/models.ts b/src/Pages/StudentPage/Artamonov/Manufacture/models.ts new file mode 100644 index 0000000..b81ea52 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Manufacture/models.ts @@ -0,0 +1,6 @@ +export type Manufacture = { + id: number, + name: string, + city: string, + country: string +} \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Order/Order.tsx b/src/Pages/StudentPage/Artamonov/Order/Order.tsx new file mode 100644 index 0000000..1a9f644 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Order/Order.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +const Order = () => { + return ( + + Order page + + ); +}; + +export default Order; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Product/Popups/CreateProductPopup.tsx b/src/Pages/StudentPage/Artamonov/Product/Popups/CreateProductPopup.tsx new file mode 100644 index 0000000..0d91691 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Product/Popups/CreateProductPopup.tsx @@ -0,0 +1,156 @@ +import React, { useEffect, useState } from 'react'; +import ArtamonovPopup, { IPopup } from "../../../../../Components/Artamonov/ArtamonovPopup/ArtamonovPopup"; +import { Button, FormControl, InputLabel, MenuItem, Select, TextField } from "@mui/material"; +import { Product } from "../models"; +import { artamonovAxios } from '../../ArtamonovPage'; +import { Category } from "../../Category/models"; +import { Manufacture } from "../../Manufacture/models"; + +type Props = IPopup & { + onCreate: (newProduct: Product) => void; +} + +const CreateProductPopup = ({ open, onClose, onCreate }: Props) => { + + const createProduct = () => { + artamonovAxios.post<{ item: Product }>('https://canstudy.ru/orderapi/Product', + { + ...Product + }) + .then(res => { + onCreate(res.data.item) + }) + } + + const [categoryList, setCategoryList] = useState([]) + + const [manufactureList, setManufactureList] = useState([]) + + const getCategories = () => { + artamonovAxios.get<{ items: Category[] }>('https://canstudy.ru/orderapi/category/list') + .then(res => { + setCategoryList(res.data.items); + }) + } + + const getManufacturies = () => { + artamonovAxios.get<{ items: Manufacture[] }>('https://canstudy.ru/orderapi/manufacturer/list') + .then(res => { + setManufactureList(res.data.items); + }) + } + + useEffect(() => { + getCategories(); + getManufacturies(); + }, []) + + const [Product, setProduct] = useState({ + categoryId: 0, + categoryName: "", + cost: 0, + description: "", + id: 0, + manufacturerId: 0, + manufacturerName: "", + name: "" + }) + + const onCreateClick = () => { + createProduct(); + + onClose(); + } + + console.log(Product) + + return ( + onClose()} + > + + + + + + setProduct(prev => ({ ...prev, name: e.target.value }))} + /> + + setProduct(prev => ({ ...prev, description: e.target.value }))} + /> + + + setProduct(prev => ({ ...prev, cost: e.target.value as any }))} + /> + + + + setProduct(prev => ({ ...prev, categoryId: e.target.value as any }))} + > + {categoryList.map((el, i) => + {el.name}) + } + + + + + + + setProduct(prev => ({ ...prev, manufacturerId: e.target.value as any }))} + > + {manufactureList.map((el, i) => + {el.name}) + } + + + + + + + onCreateClick()} + > + + + + + + + ); +}; + +export default CreateProductPopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Product/Popups/EditProductPopup.tsx b/src/Pages/StudentPage/Artamonov/Product/Popups/EditProductPopup.tsx new file mode 100644 index 0000000..990603f --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Product/Popups/EditProductPopup.tsx @@ -0,0 +1,139 @@ +import React, { useEffect, useState } from 'react'; +import ArtamonovPopup, { IPopup } from "../../../../../Components/Artamonov/ArtamonovPopup/ArtamonovPopup"; +import { Button, FormControl, InputLabel, MenuItem, Select, TextField } from "@mui/material"; +import { Product } from "../models"; +import { artamonovAxios } from "../../ArtamonovPage"; +import { Category } from "../../Category/models"; +import { Manufacture } from "../../Manufacture/models"; + +type Props = IPopup & { + onEdit: (newProduct: Product) => void; + Product: Product +} + +const EditProductPopup = ({ open, onClose, Product: ProductEdit, onEdit }: Props) => { + + const [Product, setProduct] = useState(ProductEdit) + + const onEditClick = () => { + + artamonovAxios.patch<{ item: Product }>('https://canstudy.ru/orderapi/Product', + { + item: { + ...Product + } + }) + .then(res => { + onEdit(res.data.item) + onClose(); + }) + } + + const [categoryList, setCategoryList] = useState([]) + + const [manufactureList, setManufactureList] = useState([]) + + const getCategories = () => { + artamonovAxios.get<{ items: Category[] }>('https://canstudy.ru/orderapi/category/list') + .then(res => { + setCategoryList(res.data.items); + }) + } + + const getManufacturies = () => { + artamonovAxios.get<{ items: Manufacture[] }>('https://canstudy.ru/orderapi/manufacturer/list') + .then(res => { + setManufactureList(res.data.items); + }) + } + + useEffect(() => { + getCategories(); + getManufacturies(); + }, []) + + + return ( + onClose()} + > + + setProduct(prev => ({ ...prev, name: e.target.value }))} + /> + + setProduct(prev => ({ ...prev, description: e.target.value }))} + /> + + + setProduct(prev => ({ ...prev, cost: e.target.value as any }))} + /> + + + + setProduct(prev => ({ ...prev, categoryId: e.target.value as any }))} + > + {categoryList.map((el, i) => + {el.name}) + } + + + + + + + setProduct(prev => ({ ...prev, manufacturerId: e.target.value as any }))} + > + {manufactureList.map((el, i) => + {el.name}) + } + + + + + + onEditClick()} + > + + + + + + + ); +}; + +export default EditProductPopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Product/Product.tsx b/src/Pages/StudentPage/Artamonov/Product/Product.tsx new file mode 100644 index 0000000..10d2be7 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Product/Product.tsx @@ -0,0 +1,179 @@ +import { Button, IconButton } from '@mui/material'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import React, { useEffect, useState } from 'react'; +import { Product } from './models'; +import DeleteIcon from '@mui/icons-material/Delete'; +import EditIcon from '@mui/icons-material/Edit'; +import { artamonovAxios } from '../ArtamonovPage'; +import CreateProductPopup from "./Popups/CreateProductPopup"; +import EditProductPopup from "./Popups/EditProductPopup"; +//import CreateProductPopup from "./Popups/CreateProductPopup"; +//import EditProductPopup from "./Popups/EditProductPopup"; + + +const ProductPage = () => { + + const [ProductList, setProductList] = useState([]) + + const getProducts = () => { + artamonovAxios.get<{ items: Product[] }>('https://canstudy.ru/orderapi/Product/list') + .then(res => { + setProductList(res.data.items); + }) + } + + + useEffect(() => { + getProducts(); + }, []) + + + const onDeleteClick = (id: number) => { + artamonovAxios.delete(`https://canstudy.ru/orderapi/Product/${id}`) + .then(res => { + setProductList(prev => + prev.filter(el => el.id !== id) + ) + }) + } + + const onEditClick = (id: number) => { + const Product = ProductList.find(el => el.id === id)!; + setEditProduct(Product) + } + + const onCreate = (Product: Product) => { + setProductList(prev => [...prev, Product]) + } + + const onEdit = (Product: Product) => { + setProductList(prev => { + + const curProduct = prev.find(el => el.id === Product.id)!; + + if (curProduct) { + curProduct.name = Product.name; + curProduct.description = Product.description; + curProduct.cost = Product.cost; + curProduct.manufacturerId = Product.manufacturerId; + curProduct.manufacturerName = Product.manufacturerName; + curProduct.categoryId = Product.categoryId; + curProduct.categoryName = Product.categoryName; + } + + return [...prev] + }) + } + + const columns: GridColDef[] = [ + { + field: 'id', + headerName: 'Id' + }, + { + field: 'name', + headerName: '', + flex: 1 + }, + { + field: 'cost', + headerName: '', + flex: 1 + }, + { + field: 'categoryName', + headerName: '', + flex: 1 + }, + { + field: 'manufacturerName', + headerName: '', + flex: 1 + }, + { + field: '', + headerName: '', + renderCell: (e: any) => { + return + + onEditClick(e.row.id)} + > + + + + onDeleteClick(e.row.id)} + aria-label="delete" + > + + + + } + } + ] + + const [createPopupOpened, setCreatePopupOpened] = useState(false) + + const [editProduct, setEditProduct] = useState(null) + + return ( + + + {createPopupOpened && setCreatePopupOpened(false)} + onCreate={(newProduct) => onCreate(newProduct)} + />} + + + {editProduct !== null && setEditProduct(null)} + Product={editProduct} + onEdit={(editProduct) => onEdit(editProduct)} + />} + + + + + + + setCreatePopupOpened(true)} + > + + + + + + + + + + + + ); +}; + +export default ProductPage; \ No newline at end of file diff --git a/src/Pages/StudentPage/Artamonov/Product/models.tsx b/src/Pages/StudentPage/Artamonov/Product/models.tsx new file mode 100644 index 0000000..12cb9e4 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Product/models.tsx @@ -0,0 +1,10 @@ +export type Product = { + id: number, + categoryId: number, + manufacturerId: number, + name: string, + cost: number, + description: string, + categoryName: string, + manufacturerName: string +} diff --git a/src/Pages/StudentPage/Artamonov/Purchase/Purchase.tsx b/src/Pages/StudentPage/Artamonov/Purchase/Purchase.tsx new file mode 100644 index 0000000..16a2d90 --- /dev/null +++ b/src/Pages/StudentPage/Artamonov/Purchase/Purchase.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +const Purchase = () => { + return ( + + Purchase page + + ); +}; + +export default Purchase; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/AsideMenu/AsideMenu.scss b/src/Pages/StudentPage/Kurgankov/AsideMenu/AsideMenu.scss new file mode 100644 index 0000000..818ca2b --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/AsideMenu/AsideMenu.scss @@ -0,0 +1,4 @@ +.aside { + width: 15em; + border: 1px solid black; +} \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/AsideMenu/AsideMenu.tsx b/src/Pages/StudentPage/Kurgankov/AsideMenu/AsideMenu.tsx new file mode 100644 index 0000000..8e1b765 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/AsideMenu/AsideMenu.tsx @@ -0,0 +1,46 @@ +import { List, ListItem, ListItemButton, ListItemText } from '@mui/material'; +import React from 'react'; +import "./AsideMenu.scss"; +import { useNavigate } from "react-router-dom"; + +const AsideMenu = () => { + + const navigate = useNavigate(); + + return ( + + + + navigate('category')}> + + + + + + navigate('manufacture')}> + + + + + + navigate('client')}> + + + + + + navigate('product')}> + + + + + + navigate('order')}> + + + + + ); +}; + +export default AsideMenu; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Category/CategoryPage.tsx b/src/Pages/StudentPage/Kurgankov/Category/CategoryPage.tsx new file mode 100644 index 0000000..c139236 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Category/CategoryPage.tsx @@ -0,0 +1,155 @@ +import { Button, IconButton } from '@mui/material'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import React, { useEffect, useState } from 'react'; +import { Category } from './models'; +//import Category from "./models"; +import DeleteIcon from '@mui/icons-material/Delete'; +import EditIcon from '@mui/icons-material/Edit'; +import KurgankovPage, { kurgankovAxios } from '../KurgankovPage'; +import KurgankovPopup from '../../../../Components/Kurgankov/KurgankovPopup/KurgankovPopup'; +import CreateCategoryPopup from "./Popups/CreateCategoryPopup"; +import EditCategoryPopup from "./Popups/EditCategoryPopup"; +import axios from 'axios'; + +const CategoryPage = () => { + + const [categoryList, setCategoryList] = useState([]) + + const getCategories = () => { + kurgankovAxios.get<{ items: Category[] }>('https://canstudy.ru/orderapi/category/list') + .then(res => { + setCategoryList(res.data.items); + }) + } + + + useEffect(() => { + getCategories(); + }, []) + + + + const onDeleteClick = (id: number) => { + kurgankovAxios.delete(`https://canstudy.ru/orderapi/category/${id}`) + .then(res => { + setCategoryList(prev => + prev.filter(el => el.id !== id) + ) + }) + } + + const onEditClick = (id: number) => { + const category = categoryList.find(el => el.id === id)!; + setEditCategory(category) + } + + const onCreate = (category: Category) => { + setCategoryList(prev => [...prev, category]) + } + + const onEdit = (category: Category) => { + setCategoryList(prev => { + const curCategory = prev.find(el => el.id === category.id)!; + + curCategory.name = category.name; + + return [...prev] + }) + } + + const columns: GridColDef[] = [ + { + field: 'id', + headerName: 'Id' + }, + { + field: 'name', + headerName: 'Name', + flex: 1 + }, + { + field: '', + headerName: '', + renderCell: (e: any) => { + return + + onEditClick(e.row.id)} + > + + + + onDeleteClick(e.row.id)} + aria-label="delete" + > + + + + } + } + ] + + const [createPopupOpened, setCreatePopupOpened] = useState(false) + + const [editCategory, setEditCategory] = useState(null) + + return ( + + + {createPopupOpened && setCreatePopupOpened(false)} + onCreate={(newCategory) => onCreate(newCategory)} + />} + + {editCategory !== null && setEditCategory(null)} + category={editCategory} + onEdit={(editCategory) => onEdit(editCategory)} + />} + + + + Категории + + + setCreatePopupOpened(true)} + > + Создать категорию + + + + + + + + + + + ); +}; + +export default CategoryPage; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Category/Popups/CreateCategoryPopup.tsx b/src/Pages/StudentPage/Kurgankov/Category/Popups/CreateCategoryPopup.tsx new file mode 100644 index 0000000..9829cd6 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Category/Popups/CreateCategoryPopup.tsx @@ -0,0 +1,69 @@ +import React, { useEffect, useState } from 'react'; +import KurgankovPopup, { IPopup } from "../../../../../Components/Kurgankov/KurgankovPopup/KurgankovPopup"; +import { Button, TextField } from "@mui/material"; +import { Category } from "../models"; +import axios from 'axios'; +import { kurgankovAxios } from '../../KurgankovPage'; + +type Props = IPopup & { + onCreate: (newCategory: Category) => void; +} + +const CreateCategoryPopup = ({ open, onClose, onCreate }: Props) => { + + const createCategory = () => { + kurgankovAxios.post<{ item: Category }>('https://canstudy.ru/orderapi/category', + { + name: categoryName + }) + .then(res => { + onCreate(res.data.item) + }) + } + + + const [categoryName, setCategoryName] = useState('') + + const onCreateClick = () => { + createCategory(); + + onClose(); + } + + return ( + onClose()} + > + + setCategoryName(e.target.value)} + /> + + + onCreateClick()} + > + + + + + + + ); +}; + +export default CreateCategoryPopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Category/Popups/EditCategoryPopup.tsx b/src/Pages/StudentPage/Kurgankov/Category/Popups/EditCategoryPopup.tsx new file mode 100644 index 0000000..a0ba88e --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Category/Popups/EditCategoryPopup.tsx @@ -0,0 +1,69 @@ +import React, { useState } from 'react'; +import KurgankovPopup, { IPopup } from "../../../../../Components/Kurgankov/KurgankovPopup/KurgankovPopup"; +import { Button, TextField } from "@mui/material"; +import { Category } from "../models"; +import { kurgankovAxios } from "../../KurgankovPage"; + +type Props = IPopup & { + onEdit: (newCategory: Category) => void; + category: Category +} + +const EditCategoryPopup = ({ open, onClose, category, onEdit }: Props) => { + + const [categoryEdit, setCategoryEdit] = useState(category) + + const onEditClick = () => { + + kurgankovAxios.patch<{ item: Category }>('https://canstudy.ru/orderapi/category', + { + item: { + id: category.id, + name: category.name, + } + }) + .then(res => { + onEdit(categoryEdit) + onClose(); + }) + } + + return ( + onClose()} + > + + + setCategoryEdit(prev => ({ ...prev, name: e.target.value })) + } + /> + + + onEditClick()} + > + + + + + + + ); +}; + +export default EditCategoryPopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Category/models.ts b/src/Pages/StudentPage/Kurgankov/Category/models.ts new file mode 100644 index 0000000..a893b01 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Category/models.ts @@ -0,0 +1,4 @@ +export type Category = { + id:number, + name:string +} \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Client/Client.tsx b/src/Pages/StudentPage/Kurgankov/Client/Client.tsx new file mode 100644 index 0000000..3fc7eec --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Client/Client.tsx @@ -0,0 +1,186 @@ +import { Button, IconButton } from '@mui/material'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import React, { useEffect, useState } from 'react'; +import { Client } from './models'; +import DeleteIcon from '@mui/icons-material/Delete'; +import EditIcon from '@mui/icons-material/Edit'; +import { kurgankovAxios } from '../KurgankovPage'; +import CreateClientPopup from "./Popups/CreateClientPopup"; +import EditClientPopup from "./Popups/EditClientPopup"; +import MaleIcon from '@mui/icons-material/Male'; +import FemaleIcon from '@mui/icons-material/Female'; + +const ClientPage = () => { + + const [ClientList, setClientList] = useState([]) + + const getClients = () => { + kurgankovAxios.get<{ items: Client[] }>('https://canstudy.ru/orderapi/Client/list') + .then(res => { + setClientList(res.data.items); + }) + } + + + useEffect(() => { + getClients(); + }, []) + + + const onDeleteClick = (id: number) => { + kurgankovAxios.delete(`https://canstudy.ru/orderapi/Client/${id}`) + .then(res => { + setClientList(prev => + prev.filter(el => el.id !== id) + ) + }) + } + + const onEditClick = (id: number) => { + const Client = ClientList.find(el => el.id === id)!; + setEditClient(Client) + } + + const onCreate = (Client: Client) => { + setClientList(prev => [...prev, Client]) + } + + const onEdit = (Client: Client) => { + setClientList(prev => { + const curClient = prev.find(el => el.id === Client.id)!; + + if (curClient) { + curClient.firstName = Client.firstName; + curClient.lastName = Client.lastName; + curClient.phoneNumber = Client.phoneNumber; + curClient.email = Client.email; + curClient.sex = Client.sex; + } + + return [...prev] + }) + } + + const columns: GridColDef[] = [ + { + field: 'id', + headerName: 'Id' + }, + { + field: 'sex', + headerName: '', + flex: 1, + renderCell: (e) => { + if (e.value?.toString() === "0") + return + + return + } + }, + { + field: 'firstName', + headerName: '', + flex: 1 + }, + { + field: 'lastName', + headerName: '', + flex: 1 + }, + { + field: 'email', + headerName: '', + flex: 1 + }, + { + field: 'phoneNumber', + headerName: '', + flex: 1 + }, + { + field: '', + headerName: '', + renderCell: (e: any) => { + return + + onEditClick(e.row.id)} + > + + + + onDeleteClick(e.row.id)} + aria-label="delete" + > + + + + } + } + ] + + const [createPopupOpened, setCreatePopupOpened] = useState(false) + + const [editClient, setEditClient] = useState(null) + + return ( + + + {createPopupOpened && setCreatePopupOpened(false)} + onCreate={(newClient) => onCreate(newClient)} + />} + + + {editClient !== null && setEditClient(null)} + client={editClient} + onEdit={(editClient) => onEdit(editClient)} + />} + + + + + + + setCreatePopupOpened(true)} + > + + + + + + + + + + + + ); +}; + +export default ClientPage; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Client/Popups/CreateClientPopup.tsx b/src/Pages/StudentPage/Kurgankov/Client/Popups/CreateClientPopup.tsx new file mode 100644 index 0000000..6804178 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Client/Popups/CreateClientPopup.tsx @@ -0,0 +1,116 @@ +import React, { useEffect, useState } from 'react'; +import KurgankovPopup, { IPopup } from "../../../../../Components/Kurgankov/KurgankovPopup/KurgankovPopup"; +import { Button, FormControl, InputLabel, MenuItem, Select, TextField } from "@mui/material"; +import { Client } from "../models"; +import axios from 'axios'; +import { kurgankovAxios } from '../../KurgankovPage'; + +type Props = IPopup & { + onCreate: (newClient: Client) => void; +} + +const CreateClientPopup = ({ open, onClose, onCreate }: Props) => { + + const createClient = () => { + kurgankovAxios.post<{ item: Client }>('https://canstudy.ru/orderapi/Client', + { + ...client + }) + .then(res => { + onCreate(res.data.item) + }) + } + + + const [client, setClient] = useState({ + sex: 0, + firstName: "", + lastName: "", + email: "", + phoneNumber: "", + id: 0, + }) + + const onCreateClick = () => { + createClient(); + + onClose(); + } + + return ( + onClose()} + > + + + + + setClient(prev => ({ ...prev, sex: e.target.value as any }))} + > + + + + + + + setClient(prev => ({ ...prev, firstName: e.target.value }))} + /> + + setClient(prev => ({ ...prev, lastName: e.target.value }))} + /> + + setClient(prev => ({ ...prev, email: e.target.value }))} + /> + + setClient(prev => ({ ...prev, phoneNumber: e.target.value }))} + /> + + + onCreateClick()} + > + + + + + + + ); +}; + +export default CreateClientPopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Client/Popups/EditClientPopup.tsx b/src/Pages/StudentPage/Kurgankov/Client/Popups/EditClientPopup.tsx new file mode 100644 index 0000000..fd5d3a1 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Client/Popups/EditClientPopup.tsx @@ -0,0 +1,104 @@ +import React, { useState } from 'react'; +import KurgankovPopup, { IPopup } from "../../../../../Components/Kurgankov/KurgankovPopup/KurgankovPopup"; +import { Button, FormControl, InputLabel, MenuItem, Select, TextField } from "@mui/material"; +import { Client } from "../models"; +import { kurgankovAxios } from "../../KurgankovPage"; + +type Props = IPopup & { + onEdit: (newClient: Client) => void; + client: Client +} + +const EditClientPopup = ({ open, onClose, client: clientEdit, onEdit }: Props) => { + + const [client, setClient] = useState(clientEdit) + + const onEditClick = () => { + + kurgankovAxios.patch<{ item: Client }>('https://canstudy.ru/orderapi/Client', + { + item: { + ...client + } + }) + .then(res => { + onEdit(res.data.item) + onClose(); + }) + } + + return ( + onClose()} + > + + + + setClient(prev => ({ ...prev, sex: e.target.value as any }))} + > + + + + + + + setClient(prev => ({ ...prev, firstName: e.target.value }))} + /> + + setClient(prev => ({ ...prev, lastName: e.target.value }))} + /> + + setClient(prev => ({ ...prev, email: e.target.value }))} + /> + + setClient(prev => ({ ...prev, phoneNumber: e.target.value }))} + /> + + + onEditClick()} + > + + + + + + + ); +}; + +export default EditClientPopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Client/models.tsx b/src/Pages/StudentPage/Kurgankov/Client/models.tsx new file mode 100644 index 0000000..32338b0 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Client/models.tsx @@ -0,0 +1,8 @@ +export type Client = { + id: number, + sex: number, + firstName: string, + lastName: string, + email: string, + phoneNumber: string +} \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/KurgankovPage.scss b/src/Pages/StudentPage/Kurgankov/KurgankovPage.scss new file mode 100644 index 0000000..e85c842 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/KurgankovPage.scss @@ -0,0 +1,4 @@ +.self_page_content { + display:flex; + gap:1em; +} \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/KurgankovPage.tsx b/src/Pages/StudentPage/Kurgankov/KurgankovPage.tsx new file mode 100644 index 0000000..67daf08 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/KurgankovPage.tsx @@ -0,0 +1,47 @@ +import React, { useEffect } from 'react'; +import Header from "../../../Components/Header/Header"; +import ContentBlock from "../../../Components/ContentBlock/ContentBlock"; +import AsideMenu from "./AsideMenu/AsideMenu"; +import { Outlet } from "react-router-dom"; +import "./KurgankovPage.scss"; +import axios from 'axios'; + + +export const kurgankovAxios = axios.create({}) + + +const KurgankovPage = () => { + + const doLogin = () => { + axios.post<{ authToken: string }>('https://canstudy.ru/orderapi/user/login', { + identifier: '300fe41b-d135-4e4e-ab44-95eaf24273d5' + }) + .then(res => { + kurgankovAxios + .defaults + .headers + .common['Authorization'] = 'Bearer ' + res.data.authToken + }) + } + + + useEffect(() => { + doLogin(); + }, []) + + return ( + + + + + + + + + + + + ); +}; + +export default KurgankovPage; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Manufacture/ManufacturePage.tsx b/src/Pages/StudentPage/Kurgankov/Manufacture/ManufacturePage.tsx new file mode 100644 index 0000000..2a408bc --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Manufacture/ManufacturePage.tsx @@ -0,0 +1,165 @@ +import { Button, IconButton } from '@mui/material'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import React, { useEffect, useState } from 'react'; +//import manufacture from "./models"; +import DeleteIcon from '@mui/icons-material/Delete'; +import EditIcon from '@mui/icons-material/Edit'; +import { kurgankovAxios } from '../KurgankovPage'; +import { Manufacture } from "./models"; +import CreateManufacturePopup from "./Popups/CreateManufacturePopup"; +import EditManufacturePopup from "./Popups/EditManufacturePopup"; + +const ManufacturePage = () => { + + const [manufactureList, setManufactureList] = useState([]) + + const getManufacturies = () => { + kurgankovAxios.get<{ items: Manufacture[] }>('https://canstudy.ru/orderapi/manufacturer/list') + .then(res => { + setManufactureList(res.data.items); + }) + } + + + useEffect(() => { + getManufacturies(); + }, []) + + + const onDeleteClick = (id: number) => { + + kurgankovAxios.delete(`https://canstudy.ru/orderapi/manufacturer/${id}`) + .then(res => { + setManufactureList(prev => + prev.filter(el => el.id !== id) + ) + }) + } + + const onEditClick = (id: number) => { + const manufacture = manufactureList.find(el => el.id === id)!; + setEditmanufacture(manufacture) + } + + const onCreate = (manufacture: Manufacture) => { + setManufactureList(prev => [...prev, manufacture]) + } + + const onEdit = (manufacture: Manufacture) => { + setManufactureList(prev => { + const curmanufacture = prev.find(el => el.id === manufacture.id)!; + + curmanufacture.name = manufacture.name; + curmanufacture.country = manufacture.country; + curmanufacture.city = manufacture.city; + + return [...prev] + }) + } + + const columns: GridColDef[] = [ + { + field: 'id', + headerName: 'Id' + }, + { + field: 'name', + headerName: '', + flex: 1 + }, + { + field: 'country', + headerName: '', + flex: 1 + }, + { + field: 'city', + headerName: '', + flex: 1 + }, + { + field: '', + headerName: '', + renderCell: (e: any) => { + return + + onEditClick(e.row.id)} + > + + + + onDeleteClick(e.row.id)} + aria-label="delete" + > + + + + } + } + ] + + const [createPopupOpened, setCreatePopupOpened] = useState(false) + + const [editmanufacture, setEditmanufacture] = useState(null) + + return ( + + + {createPopupOpened && setCreatePopupOpened(false)} + onCreate={(newManufacture) => onCreate(newManufacture)} + />} + + {editmanufacture !== null && setEditmanufacture(null)} + Manufacture={editmanufacture} + onEdit={(editmanufacture) => onEdit(editmanufacture)} + />} + + + + + + + setCreatePopupOpened(true)} + > + + + + + + + + + + + + ); +}; + +export default ManufacturePage; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Manufacture/Popups/CreateManufacturePopup.tsx b/src/Pages/StudentPage/Kurgankov/Manufacture/Popups/CreateManufacturePopup.tsx new file mode 100644 index 0000000..aece213 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Manufacture/Popups/CreateManufacturePopup.tsx @@ -0,0 +1,96 @@ +import React, { useState } from 'react'; +import KurgankovPopup, { IPopup } from "../../../../../Components/Kurgankov/KurgankovPopup/KurgankovPopup"; +import { Button, TextField } from "@mui/material"; +import { Manufacture } from "../models"; +import { kurgankovAxios } from '../../KurgankovPage'; + +type Props = IPopup & { + onCreate: (newManufacture: Manufacture) => void; +} + +const CreateManufacturePopup = ({ open, onClose, onCreate }: Props) => { + + const createManufacture = () => { + kurgankovAxios.post<{ item: Manufacture }>('https://canstudy.ru/orderapi/manufacturer', + { + name: manufacture.name, + city: manufacture.city, + country: manufacture.country + }) + .then(res => { + onCreate(res.data.item) + }) + } + + const [manufacture, setManufacture] = useState({ + id: 0, + name: '', + country: '', + city: '' + }) + + const onCreateClick = () => { + createManufacture(); + + onClose(); + } + + return ( + onClose()} + > + + setManufacture(prev => ( + { ...prev, name: e.target.value } + ))} + /> + + setManufacture(prev => ( + { ...prev, country: e.target.value } + ))} + /> + + setManufacture(prev => ( + { ...prev, city: e.target.value } + ))} + /> + + + onCreateClick()} + > + + + + + + + ); +}; + +export default CreateManufacturePopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Manufacture/Popups/EditManufacturePopup.tsx b/src/Pages/StudentPage/Kurgankov/Manufacture/Popups/EditManufacturePopup.tsx new file mode 100644 index 0000000..714c4e7 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Manufacture/Popups/EditManufacturePopup.tsx @@ -0,0 +1,91 @@ +import React, { useState } from 'react'; +import KurgankovPopup, { IPopup } from "../../../../../Components/Kurgankov/KurgankovPopup/KurgankovPopup"; +import { Button, TextField } from "@mui/material"; +import { Manufacture } from "../models"; +import { kurgankovAxios } from "../../KurgankovPage"; +import { Category } from "../../Category/models"; + +type Props = IPopup & { + onEdit: (newManufacture: Manufacture) => void; + Manufacture: Manufacture +} + +const EditManufacturePopup = ({ open, onClose, Manufacture, onEdit }: Props) => { + + const [ManufactureEdit, setManufactureEdit] = useState(Manufacture) + + const onEditClick = () => { + kurgankovAxios.patch<{ item: Manufacture }>('https://canstudy.ru/orderapi/manufacturer', + { + item: { + id: ManufactureEdit.id, + name: ManufactureEdit.name, + city: ManufactureEdit.city, + country: ManufactureEdit.country, + } + }) + .then(res => { + onEdit(ManufactureEdit) + onClose(); + }) + } + + return ( + onClose()} + > + + + setManufactureEdit(prev => ({ ...prev, name: e.target.value })) + } + /> + + setManufactureEdit(prev => ( + { ...prev, country: e.target.value } + ))} + /> + + setManufactureEdit(prev => ( + { ...prev, city: e.target.value } + ))} + /> + + + onEditClick()} + > + + + + + + + ); +}; + +export default EditManufacturePopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Manufacture/models.ts b/src/Pages/StudentPage/Kurgankov/Manufacture/models.ts new file mode 100644 index 0000000..b81ea52 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Manufacture/models.ts @@ -0,0 +1,6 @@ +export type Manufacture = { + id: number, + name: string, + city: string, + country: string +} \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Order/Order.tsx b/src/Pages/StudentPage/Kurgankov/Order/Order.tsx new file mode 100644 index 0000000..1a9f644 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Order/Order.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +const Order = () => { + return ( + + Order page + + ); +}; + +export default Order; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Product/Popups/CreateProductPopup.tsx b/src/Pages/StudentPage/Kurgankov/Product/Popups/CreateProductPopup.tsx new file mode 100644 index 0000000..f5ec51b --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Product/Popups/CreateProductPopup.tsx @@ -0,0 +1,156 @@ +import React, { useEffect, useState } from 'react'; +import KurgankovPopup, { IPopup } from "../../../../../Components/Kurgankov/KurgankovPopup/KurgankovPopup"; +import { Button, FormControl, InputLabel, MenuItem, Select, TextField } from "@mui/material"; +import { Product } from "../models"; +import { kurgankovAxios } from '../../KurgankovPage'; +import { Category } from "../../Category/models"; +import { Manufacture } from "../../Manufacture/models"; + +type Props = IPopup & { + onCreate: (newProduct: Product) => void; +} + +const CreateProductPopup = ({ open, onClose, onCreate }: Props) => { + + const createProduct = () => { + kurgankovAxios.post<{ item: Product }>('https://canstudy.ru/orderapi/Product', + { + ...Product + }) + .then(res => { + onCreate(res.data.item) + }) + } + + const [categoryList, setCategoryList] = useState([]) + + const [manufactureList, setManufactureList] = useState([]) + + const getCategories = () => { + kurgankovAxios.get<{ items: Category[] }>('https://canstudy.ru/orderapi/category/list') + .then(res => { + setCategoryList(res.data.items); + }) + } + + const getManufacturies = () => { + kurgankovAxios.get<{ items: Manufacture[] }>('https://canstudy.ru/orderapi/manufacturer/list') + .then(res => { + setManufactureList(res.data.items); + }) + } + + useEffect(() => { + getCategories(); + getManufacturies(); + }, []) + + const [Product, setProduct] = useState({ + categoryId: 0, + categoryName: "", + cost: 0, + description: "", + id: 0, + manufacturerId: 0, + manufacturerName: "", + name: "" + }) + + const onCreateClick = () => { + createProduct(); + + onClose(); + } + + console.log(Product) + + return ( + onClose()} + > + + + + + + setProduct(prev => ({ ...prev, name: e.target.value }))} + /> + + setProduct(prev => ({ ...prev, description: e.target.value }))} + /> + + + setProduct(prev => ({ ...prev, cost: e.target.value as any }))} + /> + + + + setProduct(prev => ({ ...prev, categoryId: e.target.value as any }))} + > + {categoryList.map((el, i) => + {el.name}) + } + + + + + + + setProduct(prev => ({ ...prev, manufacturerId: e.target.value as any }))} + > + {manufactureList.map((el, i) => + {el.name}) + } + + + + + + + onCreateClick()} + > + + + + + + + ); +}; + +export default CreateProductPopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Product/Popups/EditProductPopup.tsx b/src/Pages/StudentPage/Kurgankov/Product/Popups/EditProductPopup.tsx new file mode 100644 index 0000000..11c3b3c --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Product/Popups/EditProductPopup.tsx @@ -0,0 +1,139 @@ +import React, { useEffect, useState } from 'react'; +import KurgankovPopup, { IPopup } from "../../../../../Components/Kurgankov/KurgankovPopup/KurgankovPopup"; +import { Button, FormControl, InputLabel, MenuItem, Select, TextField } from "@mui/material"; +import { Product } from "../models"; +import { kurgankovAxios } from "../../KurgankovPage"; +import { Category } from "../../Category/models"; +import { Manufacture } from "../../Manufacture/models"; + +type Props = IPopup & { + onEdit: (newProduct: Product) => void; + Product: Product +} + +const EditProductPopup = ({ open, onClose, Product: ProductEdit, onEdit }: Props) => { + + const [Product, setProduct] = useState(ProductEdit) + + const onEditClick = () => { + + kurgankovAxios.patch<{ item: Product }>('https://canstudy.ru/orderapi/Product', + { + item: { + ...Product + } + }) + .then(res => { + onEdit(res.data.item) + onClose(); + }) + } + + const [categoryList, setCategoryList] = useState([]) + + const [manufactureList, setManufactureList] = useState([]) + + const getCategories = () => { + kurgankovAxios.get<{ items: Category[] }>('https://canstudy.ru/orderapi/category/list') + .then(res => { + setCategoryList(res.data.items); + }) + } + + const getManufacturies = () => { + kurgankovAxios.get<{ items: Manufacture[] }>('https://canstudy.ru/orderapi/manufacturer/list') + .then(res => { + setManufactureList(res.data.items); + }) + } + + useEffect(() => { + getCategories(); + getManufacturies(); + }, []) + + + return ( + onClose()} + > + + setProduct(prev => ({ ...prev, name: e.target.value }))} + /> + + setProduct(prev => ({ ...prev, description: e.target.value }))} + /> + + + setProduct(prev => ({ ...prev, cost: e.target.value as any }))} + /> + + + + setProduct(prev => ({ ...prev, categoryId: e.target.value as any }))} + > + {categoryList.map((el, i) => + {el.name}) + } + + + + + + + setProduct(prev => ({ ...prev, manufacturerId: e.target.value as any }))} + > + {manufactureList.map((el, i) => + {el.name}) + } + + + + + + onEditClick()} + > + + + + + + + ); +}; + +export default EditProductPopup; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Product/Product.tsx b/src/Pages/StudentPage/Kurgankov/Product/Product.tsx new file mode 100644 index 0000000..d5529be --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Product/Product.tsx @@ -0,0 +1,179 @@ +import { Button, IconButton } from '@mui/material'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import React, { useEffect, useState } from 'react'; +import { Product } from './models'; +import DeleteIcon from '@mui/icons-material/Delete'; +import EditIcon from '@mui/icons-material/Edit'; +import { kurgankovAxios } from '../KurgankovPage'; +import CreateProductPopup from "./Popups/CreateProductPopup"; +import EditProductPopup from "./Popups/EditProductPopup"; +//import CreateProductPopup from "./Popups/CreateProductPopup"; +//import EditProductPopup from "./Popups/EditProductPopup"; + + +const ProductPage = () => { + + const [ProductList, setProductList] = useState([]) + + const getProducts = () => { + kurgankovAxios.get<{ items: Product[] }>('https://canstudy.ru/orderapi/Product/list') + .then(res => { + setProductList(res.data.items); + }) + } + + + useEffect(() => { + getProducts(); + }, []) + + + const onDeleteClick = (id: number) => { + kurgankovAxios.delete(`https://canstudy.ru/orderapi/Product/${id}`) + .then(res => { + setProductList(prev => + prev.filter(el => el.id !== id) + ) + }) + } + + const onEditClick = (id: number) => { + const Product = ProductList.find(el => el.id === id)!; + setEditProduct(Product) + } + + const onCreate = (Product: Product) => { + setProductList(prev => [...prev, Product]) + } + + const onEdit = (Product: Product) => { + setProductList(prev => { + + const curProduct = prev.find(el => el.id === Product.id)!; + + if (curProduct) { + curProduct.name = Product.name; + curProduct.description = Product.description; + curProduct.cost = Product.cost; + curProduct.manufacturerId = Product.manufacturerId; + curProduct.manufacturerName = Product.manufacturerName; + curProduct.categoryId = Product.categoryId; + curProduct.categoryName = Product.categoryName; + } + + return [...prev] + }) + } + + const columns: GridColDef[] = [ + { + field: 'id', + headerName: 'Id' + }, + { + field: 'name', + headerName: '', + flex: 1 + }, + { + field: 'cost', + headerName: '', + flex: 1 + }, + { + field: 'categoryName', + headerName: '', + flex: 1 + }, + { + field: 'manufacturerName', + headerName: '', + flex: 1 + }, + { + field: '', + headerName: '', + renderCell: (e: any) => { + return + + onEditClick(e.row.id)} + > + + + + onDeleteClick(e.row.id)} + aria-label="delete" + > + + + + } + } + ] + + const [createPopupOpened, setCreatePopupOpened] = useState(false) + + const [editProduct, setEditProduct] = useState(null) + + return ( + + + {createPopupOpened && setCreatePopupOpened(false)} + onCreate={(newProduct) => onCreate(newProduct)} + />} + + + {editProduct !== null && setEditProduct(null)} + Product={editProduct} + onEdit={(editProduct) => onEdit(editProduct)} + />} + + + + + + + setCreatePopupOpened(true)} + > + + + + + + + + + + + + ); +}; + +export default ProductPage; \ No newline at end of file diff --git a/src/Pages/StudentPage/Kurgankov/Product/models.tsx b/src/Pages/StudentPage/Kurgankov/Product/models.tsx new file mode 100644 index 0000000..12cb9e4 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Product/models.tsx @@ -0,0 +1,10 @@ +export type Product = { + id: number, + categoryId: number, + manufacturerId: number, + name: string, + cost: number, + description: string, + categoryName: string, + manufacturerName: string +} diff --git a/src/Pages/StudentPage/Kurgankov/Purchase/Purchase.tsx b/src/Pages/StudentPage/Kurgankov/Purchase/Purchase.tsx new file mode 100644 index 0000000..16a2d90 --- /dev/null +++ b/src/Pages/StudentPage/Kurgankov/Purchase/Purchase.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +const Purchase = () => { + return ( + + Purchase page + + ); +}; + +export default Purchase; \ No newline at end of file diff --git a/src/Pages/StudentPage/filipushko/Order/Manufacturer/ManufacturerPage.tsx b/src/Pages/StudentPage/filipushko/Order/Manufacturer/ManufacturerPage.tsx new file mode 100644 index 0000000..fe069eb --- /dev/null +++ b/src/Pages/StudentPage/filipushko/Order/Manufacturer/ManufacturerPage.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +const Manufacturer = () => { + return ( + + Test1 + + ); +}; + +export default Manufacturer; \ No newline at end of file diff --git a/src/Pages/StudentsPage.tsx b/src/Pages/StudentsPage.tsx index 9851ec6..52afafb 100644 --- a/src/Pages/StudentsPage.tsx +++ b/src/Pages/StudentsPage.tsx @@ -17,6 +17,12 @@ const StudentsPage = () => { imageSrc={'https://fanibani.ru/images/wp-content/uploads/2017/06/Volk-42.jpg'} navigateTo={'/teacher'} /> + { navigateTo={'/usanova'} /> + +