12 changed files with 1976 additions and 20 deletions
-
57frontend_reactjs/package-lock.json
-
4frontend_reactjs/package.json
-
32frontend_reactjs/src/App.tsx
-
20frontend_reactjs/src/components/FetchingData.ts
-
57frontend_reactjs/src/components/Modal.tsx
-
21frontend_reactjs/src/components/Navigate.tsx
-
19frontend_reactjs/src/components/RoleCard.tsx
-
3frontend_reactjs/src/pages/Main.tsx
-
3frontend_reactjs/src/pages/NotFound.tsx
-
26frontend_reactjs/src/pages/Roles.tsx
-
18frontend_reactjs/src/pages/Users.tsx
-
1734frontend_reactjs/yarn.lock
@ -1,24 +1,22 @@ |
|||
import { useState,useEffect } from 'react' |
|||
import Card from './components/Card' |
|||
import axios from 'axios' |
|||
interface ICard{ |
|||
firstname: string |
|||
lastname: string |
|||
email: string |
|||
} |
|||
import { BrowserRouter as Router, Routes,Route} from "react-router-dom" |
|||
import Users from "./pages/Users" |
|||
import Roles from "./pages/Roles" |
|||
import Main from "./pages/Main" |
|||
import NotFound from "./pages/NotFound" |
|||
import Navigate from "./components/Navigate" |
|||
|
|||
function App() { |
|||
// const data = [
|
|||
// {firstname:"Иван",lastname:"Петров", email:"email@test.ru"},
|
|||
// {firstname:"Алексей",lastname:"Петров", email:"email2@test.ru"},
|
|||
// {firstname:"Василиса",lastname:"Петрова", email:"email3@test.ru"}
|
|||
// ]
|
|||
const [cards, setCards] = useState<ICard[]>([]); |
|||
useEffect(()=>{axios.get("http://localhost:8000/auth/user/").then((res) =>{setCards(res.data as ICard[]);})},[]) |
|||
console.log(cards) |
|||
return ( |
|||
<> |
|||
{cards.map((card, index) => <Card key={index} {...card}/>)} |
|||
<Navigate /> |
|||
<Router> |
|||
<Routes> |
|||
<Route index path="/" element={ <Main />} /> |
|||
<Route path="/user" element={ <Users />} /> |
|||
<Route path="/role" element={ <Roles />} /> |
|||
<Route path="*" element={<NotFound />}/> |
|||
</Routes> |
|||
</Router> |
|||
</> |
|||
) |
|||
} |
|||
|
@ -0,0 +1,20 @@ |
|||
import { useState, useEffect, useMemo } from 'react'; |
|||
export function useDataFetching<T> (url:string, initData:T):T{ |
|||
const [data, setData] = useState<T>(initData); |
|||
|
|||
useEffect(() => { |
|||
const fetchData = async () => { |
|||
const response = await fetch(url); |
|||
const result = await response.json(); |
|||
setData(result); |
|||
}; |
|||
|
|||
fetchData(); |
|||
}, [url]); |
|||
console.log(data) |
|||
// Memoize the data value
|
|||
const memoizedData = useMemo<T>(() => data, [data]); |
|||
return memoizedData; |
|||
}; |
|||
|
|||
export default useDataFetching; |
@ -0,0 +1,57 @@ |
|||
export interface Props { |
|||
showModal: boolean; |
|||
} |
|||
|
|||
export default function Modal(props:Props){ |
|||
return(<> |
|||
{props.showModal && |
|||
<div id="crud-modal" tabIndex={-1} className="bg-black opacity-75 overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full" onClick={()=> console.log("click")}> |
|||
<div className="relative p-4 w-full max-w-md max-h-full" > |
|||
<div className="relative bg-white rounded-lg shadow dark:bg-gray-700"> |
|||
<div className="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600"> |
|||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white"> |
|||
Create New Product |
|||
</h3> |
|||
<button type="button" className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white" data-modal-toggle="crud-modal"> |
|||
<svg className="w-3 h-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14"> |
|||
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/> |
|||
</svg> |
|||
<span className="sr-only">Close modal</span> |
|||
</button> |
|||
</div> |
|||
<form className="p-4 md:p-5"> |
|||
<div className="grid gap-4 mb-4 grid-cols-2"> |
|||
<div className="col-span-2"> |
|||
<label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Name</label> |
|||
<input type="text" name="name" id="name" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" placeholder="Type product name" /> |
|||
</div> |
|||
<div className="col-span-2 sm:col-span-1"> |
|||
<label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Price</label> |
|||
<input type="number" name="price" id="price" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" placeholder="$2999" /> |
|||
</div> |
|||
<div className="col-span-2 sm:col-span-1"> |
|||
<label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Category</label> |
|||
<select id="category" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500"> |
|||
<option >Select category</option> |
|||
<option value="TV">TV/Monitors</option> |
|||
<option value="PC">PC</option> |
|||
<option value="GA">Gaming/Console</option> |
|||
<option value="PH">Phones</option> |
|||
</select> |
|||
</div> |
|||
<div className="col-span-2"> |
|||
<label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Product Description</label> |
|||
<textarea id="description" rows={4} className="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Write product description here"></textarea> |
|||
</div> |
|||
</div> |
|||
<button type="submit" className="text-white inline-flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"> |
|||
<svg className="me-1 -ms-1 w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fillRule="evenodd" d="M10 5a1 1 0 011 1v3h3a1 1 0 110 2h-3v3a1 1 0 11-2 0v-3H6a1 1 0 110-2h3V6a1 1 0 011-1z" clipRule="evenodd"></path></svg> |
|||
Add new product |
|||
</button> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
</div> } |
|||
|
|||
</>) |
|||
} |
@ -0,0 +1,21 @@ |
|||
export default function Navigate(){ |
|||
return( |
|||
<> |
|||
<nav className="bg-white border-gray-200 dark:bg-gray-900"> |
|||
<div className="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4"> |
|||
<ul className="font-medium flex flex-col p-4 md:p-0 mt-4 border border-gray-100 rounded-lg bg-gray-50 md:flex-row md:space-x-8 rtl:space-x-reverse md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700"> |
|||
<li> |
|||
<a href="/" className="block py-2 px-3 text-gray-900 rounded hover:bg-gray-100 md:hover:bg-transparent md:border-0 md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent">Главная</a> |
|||
</li> |
|||
<li> |
|||
<a href="/user" className="block py-2 px-3 text-gray-900 rounded hover:bg-gray-100 md:hover:bg-transparent md:border-0 md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent">Пользователи</a> |
|||
</li> |
|||
<li> |
|||
<a href="/role" className="block py-2 px-3 text-gray-900 rounded hover:bg-gray-100 md:hover:bg-transparent md:border-0 md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent">Роли</a> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</nav> |
|||
</> |
|||
) |
|||
} |
@ -0,0 +1,19 @@ |
|||
import { useState, useEffect } from 'react' |
|||
|
|||
interface IRoleCard{ |
|||
id: number |
|||
name: string |
|||
} |
|||
|
|||
function RoleCard(props:IRoleCard) { |
|||
const [curr_card, setCard] = useState<IRoleCard>({id: 1, name: "Тест"}); |
|||
useEffect(()=>{setCard(props);},[curr_card]) |
|||
return ( |
|||
<div className='block p-6 max-w-sm bg-gray-300 |
|||
rounded-lg border border-gray-500 align-items: center;'> |
|||
<div className='text-4xl text-center'>{curr_card.name}</div> |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default RoleCard |
@ -0,0 +1,3 @@ |
|||
export default function Main (){ |
|||
return ( <><h1>Main page</h1></>) |
|||
} |
@ -0,0 +1,3 @@ |
|||
export default function NotFound (){ |
|||
return ( <><h1>Page not found</h1></>) |
|||
} |
@ -0,0 +1,26 @@ |
|||
import { useState} from 'react' |
|||
import RoleCard from '../components/RoleCard' |
|||
import Modal from '../components/Modal' |
|||
import useDataFetching from '../components/FetchingData' |
|||
|
|||
interface IRoleCard{ |
|||
id: number |
|||
name: string |
|||
} |
|||
interface Props { |
|||
showModal: boolean; |
|||
} |
|||
function Users() { |
|||
const [showModal, setShowModal] = useState<Props>({showModal: false}); |
|||
const cards = useDataFetching<IRoleCard[]>("http://localhost:8000/auth/role/",[]) |
|||
|
|||
return ( |
|||
<div> |
|||
{cards.map((card, index) => <RoleCard key={index} {...card}/>)} |
|||
<button className='absolute w-0 h-0' onClick={() => setShowModal({showModal:true})}>+</button> |
|||
<Modal {...showModal}/> |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default Users |
@ -0,0 +1,18 @@ |
|||
import Card from '../components/Card' |
|||
import useDataFetching from '../components/FetchingData' |
|||
interface ICard{ |
|||
firstname: string |
|||
lastname: string |
|||
email: string |
|||
} |
|||
|
|||
function Users() { |
|||
const cards= useDataFetching<ICard[]>("http://localhost:8000/auth/user/",[]) |
|||
return ( |
|||
<div> |
|||
{cards.map((card, index) => <Card key={index} {...card}/>)} |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default Users |
1734
frontend_reactjs/yarn.lock
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue