Merge pull request #4 from more-tech4-magnum-opus/hr

add HR
This commit is contained in:
Ilia vasilenko 2022-10-09 09:12:48 +03:00 committed by GitHub
commit 80cf3475f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 790 additions and 21 deletions

BIN
public/mock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

44
src/Transaction.tsx Normal file
View File

@ -0,0 +1,44 @@
import { Button, Input } from "antd";
import React, { useState } from "react";
import { adminFetcher, hrFetcher } from "./app/hooks";
export const Transaction:React.FC = () =>{
const [user, setUser] = useState("")
const [amount, setAmount] = useState(0)
const reset = () =>{
setUser("")
setAmount(0)
}
const sendCoins = () =>{
let formData = new FormData()
formData.append("amount", amount.toString())
formData.append("username", user)
hrFetcher.post("blockchain/transact/", formData).then(e=>{
alert("Коины переведены!")
reset()
}
)
}
return(
<div className="addProduct">
<div className="addProductCard">
<div className="addProductH1">Перевод/Выдача DigitalRubles</div>
<div className="fieldsWrapper" >
<div className="InpWrapper">
<div>Telegram username</div>
<Input value={user} onChange={(e)=>setUser(e.target.value)} placeholder="firesieht"></Input>
</div>
<div className="InpWrapper">
<div>Сумма в коинах</div>
<Input value={amount} type="number" onChange={(e)=>setAmount(Number(e.target.value))} placeholder="100"></Input>
</div>
</div>
<Button onClick={()=>sendCoins()} className="btn1">Отправить</Button>
</div>
</div>
);
}

View File

@ -6,6 +6,7 @@
display: flex;
flex-direction: column;
align-items: center;
gap:30px
}
.addProductCard{
@ -109,4 +110,29 @@
align-items: center;
justify-content: center;
gap:25px
}
}
.userPreview{
background: #262626;
border-radius: 16px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 32px 64px;
gap: 36px;
width: 75%;
font-family: 'Roboto', sans-serif;
font-style: normal;
font-weight: 400;
font-size: 14px;
line-height: 22px;
/* identical to box height, or 157% */
text-align: right;
/* Character/Title .85 */
color:#fff;
}

View File

@ -47,6 +47,10 @@ export const AddAdminMarketProduct:React.FC = () =>{
link:"/admin/market/add",
name:"Cоздать товар (NFT)"
},
{
link:"/admin/transaction",
name:"История транзакций"
},
]}
name={user.name}></Header>
<div className="addProductCard">

View File

@ -60,6 +60,10 @@ export const AdminMarket:React.FC = () =>{
link:"/admin/market/add",
name:"Cоздать товар (NFT)"
},
{
link:"/admin/transaction",
name:"История транзакций"
},
]}
name={user.name}></Header>
<div className="marketCard">

View File

@ -43,7 +43,11 @@ export const AdminMarketPopUp:React.FC = () =>{
{
link:"/admin/users",
name:"Участники"
}
},
{
link:"/admin/transaction",
name:"История транзакций"
},
]}
name={user.name}></Header>
<div className="changeProductCard">

View File

@ -0,0 +1,7 @@
import React from "react";
export const AdminTransactions:React.FC = () =>{
return(<div>
</div>);
}

View File

@ -140,7 +140,7 @@ export const UserTable:React.FC = () =>{
command: user.command,
role: user.type,
respect: user.respect,
balance: user.salary,
balance: user.money,
jobTittle: user.department,
clan: user.clan_name
}) as EmployerIE ))))
@ -156,7 +156,7 @@ export const UserTable:React.FC = () =>{
command: user.command,
role: user.type,
respect: user.respect,
balance: user.salary,
balance: user.money,
jobTittle: user.department,
}) ))
} as ClanIE))
@ -202,7 +202,11 @@ export const UserTable:React.FC = () =>{
link:"/admin/market/add",
name:"Cоздать товар (NFT)"
},
{
link:"/admin/transaction",
name:"История транзакций"
},
]}
name={user.name}></Header>
<div className='changeProductCard'>

View File

@ -3,8 +3,6 @@ import { stat } from 'fs'
import { Market, Roles, SortTypes, UserIE, ProductIE, EmployerIE, ClanIE} from '../interfaces'
import { AppAdminDispatch, RootAdminState } from '../adminStore'
import { adminFetcher, useAppDispatch } from '../hooks'
import { host, token } from '../consts'
import { triggerAsyncId } from 'async_hooks'
@ -15,7 +13,7 @@ const initState = {
wallet:"123214",
balance: 100,
id:"1",
role:Roles.admin,
role:"ADMIN",
name:"Firesieht"
} as UserIE, //потом достается запросом
market: {

View File

@ -1,2 +1,4 @@
export const host = "https://dev.akarpov.ru/api/"
export const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjY1ODI0ODQxLCJpYXQiOjE2NjUyMjQ4NDEsImp0aSI6ImIyMjgzZjg0MmQ0NjQ4ZDU5MGY3N2Y1NzU2NDU3YjUyIiwidXNlcl9pZCI6NH0.-jAQjFLV9WCZEbthdpO-JDbRaL3N3eTCNr9Vo-PAUEk"
export const adminToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjY1ODcyMzQwLCJpYXQiOjE2NjUyNzIzNDAsImp0aSI6IjZkNGUxOTQ0ZTE3ZjQ4OTk4MjllYmU4Mzk2NDMwZTVlIiwidXNlcl9pZCI6Nn0.ivyEB13zMGS4liCn2N2fHUi0q9bbI8iaRWBXdiO30d4"
export const hrToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjY1ODcyMzYxLCJpYXQiOjE2NjUyNzIzNjEsImp0aSI6Ijc3ZDk1ZTI2NWJkNzQ4NGRhNWY1MjYyNDE4YWQ2NzAwIiwidXNlcl9pZCI6NX0.luP2N8g_Yp3TNEwIBMYhSTSdSpUj3-QzT4PGfoYnM0k"
export const workerToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjY1ODcyMzkxLCJpYXQiOjE2NjUyNzIzOTEsImp0aSI6IjBlYzQxOTUzMTA2NDRlOWFiNzE2NTgyZWJmZDY0MTBmIiwidXNlcl9pZCI6NH0.GULKUG-2iuEAVSPXdREC0wPbQbSsSaTLqQ3ZJblwtAk"

View File

@ -1,17 +1,38 @@
import axios from 'axios';
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootAdminState, AppAdminDispatch } from './adminStore';
import { host, token } from './consts';
import { host, adminToken, hrToken, workerToken } from './consts';
import { AppHRDispatch, RootHRState } from './hrStore';
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppAdminDispatch>();
export const useHRDispatch = () => useDispatch<AppHRDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootAdminState> = useSelector;
export const useHRSelector: TypedUseSelectorHook<RootHRState> = useSelector;
export const adminFetcher = axios.create(
{
baseURL: host,
timeout: 5000,
headers: {
Authorization: 'Bearer ' + token
Authorization: 'Bearer ' + adminToken
}
}
)
export const hrFetcher = axios.create(
{
baseURL: host,
timeout: 5000,
headers: {
Authorization: 'Bearer ' + hrToken
}
}
)
export const workerFetcher = axios.create(
{
baseURL: host,
timeout: 5000,
headers: {
Authorization: 'Bearer ' + workerToken
}
}
)

158
src/app/hr/hrSlice.ts Normal file
View File

@ -0,0 +1,158 @@
import { createAsyncThunk, createSlice, createSelector, PayloadAction } from '@reduxjs/toolkit'
import { EventAttendence, EventIE, HRIE} from '../interfaces'
import { AppHRDispatch, RootHRState } from '../hrStore'
import { hrFetcher, useAppDispatch } from '../hooks'
const initState = {
me: {} as HRIE,
events: [] as EventIE[],
currentEvent: "",
attendences: [] as EventAttendence[],
}
const hrSlice = createSlice(
{
name: "hrSlice",
initialState: initState,
reducers:{
setMe(state, action:PayloadAction<HRIE>){
state.me = action.payload
},
setEvents(state, action:PayloadAction<EventIE[]>){
state.events = action.payload
},
setAttendences(state, action:PayloadAction<EventAttendence[]>){
state.attendences = action.payload
},
setCurrentEvent(state, aaction:PayloadAction<string>){
state.currentEvent = aaction.payload
},
addEvent(state, action:PayloadAction<EventIE>){
state.events = state.events.concat([action.payload])
},
delEvent(state, action:PayloadAction<string>){
let events = state.events
let ind = 0
events.forEach((event:EventIE, index:number) => {
if(event.slug == action.payload){
ind = index
}
});
events.splice(ind, 1)
state.events = events
},
updateEvent(state, action:PayloadAction<EventIE>){
let events = state.events
events.forEach((event:EventIE, index:number) => {
if(event.slug == action.payload.slug){
events[index] = action.payload
}
});
state.events = events
},
submitAttendance(state, action:PayloadAction<string>){
let attendences = state.attendences
attendences.forEach((attendance:EventAttendence, index:number) => {
if(attendance.worker_username == action.payload){
attendences[index].attended = true
}
});
state.attendences = attendences
}
}
}
)
export async function fetchAddEvent(dispatch:AppHRDispatch, params:{name: string, about: string, starts:string, image:File}) {
//тут идет фетч
const formData = new FormData()
formData.append("name",params.name)
formData.append("about",params.about)
formData.append("image", params.image)
formData.append("starts",params.starts)
hrFetcher.post("events/", formData).then((response)=>{
dispatch(
addEvent(
{
name: response.data.name,
about: response.data.about,
slug: response.data.slug,
creator: {
wallet: "",
role: response.data.creator.type,
telegram: response.data.creator.telegram,
command: response.data.creator.command,
respect: response.data.creator.respect,
balance: response.data.creator.money,
name: response.data.creator.name
} as HRIE,
starts: response.data.starts,
image: response.data.image,
planning: Number(response.data.planning),
attended: Number(response.data.attended)
} as EventIE
)
)
})
}
export async function fetchDelEvent(dispatch:AppHRDispatch, params:string) {
hrFetcher.delete("events/" + params).then(()=>{
dispatch(delEvent(params))
})
}
export async function fetchSubmitAttendance(dispatch:AppHRDispatch, user:string, currentEvent:string){
const formData = new FormData()
formData.append("username", user)
hrFetcher.post("events/attendance/" + currentEvent + "/submit/", formData).then(response=>{
dispatch(submitAttendance(user))
})
const salaryData = new FormData()
salaryData.append("username", user)
salaryData.append("amount", "1")
hrFetcher.post("blockchain/transact/", salaryData)
}
export const getCurrentEvent = createSelector(
(state:RootHRState) => state.hrSlice.events.filter(el=> el.slug == state.hrSlice.currentEvent)[0],
(field)=>field
)
export const getEvents = createSelector(
(state:RootHRState) => state.hrSlice.events,
(field)=>field
)
export const getMe = createSelector(
(state:RootHRState) => state.hrSlice.me,
(field)=>field
)
export const {
setEvents,
setAttendences,
setCurrentEvent,
addEvent,
delEvent,
updateEvent,
submitAttendance,
setMe
} = hrSlice.actions
export default hrSlice.reducer

16
src/app/hrStore.ts Normal file
View File

@ -0,0 +1,16 @@
import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
import hrSlice from './hr/hrSlice';
export const hrStore = configureStore({
reducer: {
hrSlice: hrSlice,
},
});
export type AppHRDispatch = typeof hrStore.dispatch;
export type RootHRState = ReturnType<typeof hrStore.getState>;
export type AppHRThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootHRState,
unknown,
Action<string>
>;

View File

@ -14,7 +14,7 @@ export enum Specialities{
export interface UserIE{
wallet:string,
role:Roles
role:string
balance: number,
name:string,
}
@ -26,17 +26,32 @@ export interface EmployerIE extends UserIE{
respect: number,
telegramID: string,
command: string,
clan:string
clan:string,
money:number,
}
export interface HRIE extends UserIE{
respect:number,
command:number,
telegram: string,
}
export interface EventIE{
name:string,
description: string,
date: Date,
time:Date,
org: number;
visitors: number[]
about: string,
starts: string,
slug:string,
creator:HRIE,
image:string,
planning:number,
attended:number
}
export interface EventAttendence{
id:number,
event_slug:string,
worker_username:string,
attended:boolean
}
export interface ProductIE{

View File

@ -1,8 +1,6 @@
import "./Header.css"
import React from "react"
import { Link, useLocation, useParams } from "react-router-dom"
import axios, { AxiosHeaders } from 'axios';
import { host, token } from "../../app/consts";
interface HeaderIE{
links: {

View File

@ -1,6 +1,6 @@
import { Tag } from 'antd'
import react from 'react'
import "./style.css"
interface IUserPreview{
level: number;

View File

@ -0,0 +1,5 @@
.eventImg{
height: 50%;
max-height: 150px;
border-radius: 16px 16px 0px 0px;
}

View File

@ -0,0 +1,37 @@
import { Button } from "antd"
import React from "react"
import { useNavigate } from "react-router-dom"
import { useHRDispatch } from "../../app/hooks"
import { fetchDelEvent } from "../../app/hr/hrSlice"
import "../../components/prevMarketCard/prevMarketCard.css"
import "./eventCard.css"
interface EventCardIE{
image:string,
cost: number,
descr: string,
name:string,
members: number
slug?:string
}
export const EventCard:React.FC<EventCardIE> = (props) =>{
let dispatch = useHRDispatch()
let navigator = useNavigate()
return(
<div className="prevCard">
<img className="eventImg" src={props.image}></img>
<div className="prevCardWrapper">
<div className="prevCost">
<img src="/rub.svg"></img>
<div>{props.cost}</div>
</div>
<div className="prevCardH2">{props.name}</div>
<div className="prevCardDescr">{props.descr.split(" ").slice(0,6).join(" ")}</div>
<Button style={{width:"100%"}} onClick={()=>navigator("/hr/events/reg/" + props.slug)} className="btn2">Зарегистрировать</Button>
<Button style={{width:"100%"}} onClick={()=>fetchDelEvent(dispatch, props.slug as string)} className="btn1">Удалить ивент</Button>
</div>
</div>
)
}

View File

91
src/hr/addEvent/index.tsx Normal file
View File

@ -0,0 +1,91 @@
import "./addEvent.css"
import { Button, DatePicker, Input } from "antd";
import React, { useState } from "react"
import { useNavigate } from "react-router-dom";
import { useHRDispatch } from "../../app/hooks";
import { fetchAddEvent } from "../../app/hr/hrSlice";
import { FileUploader } from "../../components/fileUploader";
import { Header } from "../../components/Header";
import { EventCard } from "../EventCard";
export const AddEvent: React.FC = () =>{
const [name, setName] = useState("")
const [about, setAbout] = useState("")
const [starts, setStarts] = useState("")
const [image, setImage] = useState()
let navigate = useNavigate()
let dispatch = useHRDispatch()
const create = () =>{
fetchAddEvent(dispatch, {
name:name,
about:about,
starts:starts,
image:image as any
})
alert("Ивент успешно создан!")
navigate("/hr")
}
return(
<div className="addProduct">
<Header links={[
{
link:"/hr",
name:"События"
},
{
link:"/hr/addEvent",
name:"Создать событие"
},
{
link:"/hr/transaction",
name:"История транзакций"
}
]}
name={"HR"}></Header>
<div className="addProductCard">
<div className="addProductH1">Cоздать новое событие</div>
<div className="addBodyWrapper">
<EventCard
image={"/mock.png"}
cost={5}
descr={about}
name={name}
members={2}
></EventCard>
<div className="fieldsWrapper">
<div className="InpWrapper">
<div>Название</div>
<Input value={name} onChange={(e)=>setName(e.target.value)}></Input>
</div>
<div className="InpWrapper">
<div>Описание</div>
<Input value={about} onChange={(e)=>setAbout(e.target.value)}></Input>
</div>
<div className="InpWrapper">
<div>Дата проведения</div>
<DatePicker onChange={(_, datestring)=>setStarts(datestring)} />
</div>
<div className="InpWrapper">
<div>Картинка</div>
<FileUploader onResponse={(file)=>setImage(file)}></FileUploader>
</div>
</div>
</div>
<div className="addBtnWrapper">
<Button className="btn1" onClick={()=>navigate("/hr")}>Отмена</Button>
<Button className="btn2" onClick={()=>create()}>Создать</Button>
</div>
</div>
</div>
);
}

100
src/hr/index.tsx Normal file
View File

@ -0,0 +1,100 @@
import { Tag } from "antd";
import React from "react";
import { hrFetcher, useAppSelector, useHRDispatch, useHRSelector } from "../app/hooks";
import { getEvents, getMe, setEvents, setMe } from "../app/hr/hrSlice";
import { RootHRState } from "../app/hrStore";
import { EventIE, HRIE } from "../app/interfaces";
import { Header } from "../components/Header";
import { UserPreview } from "../components/userPreview";
import { EventCard } from "./EventCard";
export const HR:React.FC = () =>{
let me = useHRSelector((state:RootHRState)=>getMe(state))
let dispatch = useHRDispatch()
let events = useHRSelector((state:RootHRState)=>getEvents(state))
if (me.telegram == undefined){
hrFetcher.get("users/self/").then(response=>{
dispatch(setMe({
wallet: response.data.wallet_public_key,
role: response.data.type,
telegram: response.data.telegram,
command: response.data.command,
respect: response.data.respect,
balance: response.data.money,
name: response.data.name
} as HRIE))
})
hrFetcher.get("events/").then(resp=>{
dispatch(setEvents(resp.data.map((response:any)=>({
name: response.name,
about: response.about,
slug: response.slug,
creator: {
wallet: "",
role: response.creator.type,
telegram: response.creator.telegram,
command: response.creator.command,
respect: response.creator.respect,
balance: response.creator.money,
name: response.creator.name
} as HRIE,
starts: response.starts,
image: response.image,
planning: Number(response.planning),
attended: Number(response.attended)
} as EventIE))))
})
}
return(
<div className="addProduct">
<Header links={[
{
link:"/hr",
name:"События"
},
{
link:"/hr/addEvent",
name:"Создать событие"
},
{
link:"/hr/transaction",
name:"История транзакций"
}
]}
name={"HR"}></Header>
<div className="userPreview">
<UserPreview
level={3}
logo_url='/logo_example.png'
username='BrainBreaker'
rubles={Number(me.balance).toString()}
fio={me.name}
id={me.command}
tg={me.telegram}
tags={[<Tag color={'blue'}>HR</Tag>]}
description={"Sample"}
score={Number(me.respect).toString()}
></UserPreview>
</div>
<div className="marketCard">
<div className="addProductH1">Доступные события</div>
<div className="productWrapper">
{
events.map(event=><EventCard
image={event.image}
cost={5}
descr={event.about}
name={event.name}
members={event.planning}
slug={event.slug}
></EventCard>)
}
</div>
</div>
</div>
)
}

94
src/hr/regUsers/index.tsx Normal file
View File

@ -0,0 +1,94 @@
import React, { useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import "./regUsers.css"
import type { ColumnsType } from 'antd/es/table';
import { Button, Space, Table, Tag } from 'antd';
import { fetchSubmitAttendance, getCurrentEvent, setCurrentEvent } from "../../app/hr/hrSlice";
import { hrFetcher, useHRDispatch, useHRSelector } from "../../app/hooks";
import { RootHRState } from "../../app/hrStore";
interface DataTypeIE{
key:string,
id:number,
telegram:string,
attended: boolean
}
export const RegUsers:React.FC = () =>{
const [attendance, setAttendance] = useState([-1 as any])
let {name} = useParams()
let navigator = useNavigate()
const collator = new Intl.Collator('ru');
const data:DataTypeIE[] = []
let dispatch = useHRDispatch()
dispatch(setCurrentEvent(name as string))
if (attendance[0] == -1){
hrFetcher.get("events/attendance/"+name+"/list/").then(response=>setAttendance(response.data))
}
const columns: ColumnsType<DataTypeIE> = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
defaultSortOrder: 'descend',
sorter: (a, b) => a.id - b.id ,
},
{
title: 'Telegram',
dataIndex: 'telegram',
key: 'telegram',
sorter: (a, b) => collator.compare(a.telegram, b.telegram) ,
},
{
title: 'Респект',
dataIndex: 'telegram',
key: 'telegram',
render: text=><div>{ "5"} <img src="/respect.svg"></img></div>
},
{
title: 'Начислено',
dataIndex: 'attended',
key: 'attended',
render: text=><Tag color={text? "green":"red"}>
{text? "Да":"Нет"}
</Tag>
},
{
title: "Награда",
dataIndex: 'speciality',
key: 'speciality',
render: (_, recorder) => <Button onClick={()=>fetchSubmitAttendance(dispatch, recorder.telegram,name as string)} className="btn2">Начислить</Button>
}
]
attendance.forEach((attend)=>{
data.push({
key:attend.id,
id: attend.id,
telegram: attend.worker_username,
attended: attend.attended
} as DataTypeIE)
})
let currentEvent = useHRSelector((state:RootHRState)=>getCurrentEvent(state))
return(
<div className="userTable">
<div className="changeProductCard">
<div className="addProductH1">Участники мероприятия {currentEvent.name}</div>
<Table columns={columns} dataSource={data} />
<Button onClick={()=>navigator("/hr")} className="btn2">Назад</Button>
</div>
</div>
);
}

View File

View File

@ -0,0 +1,126 @@
import { Button, Table, Tag } from "antd";
import { ColumnsType } from "antd/es/table";
import React, { useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { adminFetcher, hrFetcher, useHRDispatch } from "../../app/hooks";
import { Header } from "../../components/Header";
interface DataTypeIE{
key:string,
type:string,
user_from:string,
user_to: string,
amount: number
}
export const TransactionHistory: React.FC = () =>{
const [transaction, setTransaction] = useState([-1] as any)
let location = useLocation()
let hr;
if (location.pathname.split("/")[1] == "hr"){
hr = true
}
if (transaction[0] == -1){
if(hr){
console.log(1)
hrFetcher.get("blockchain/history/").then(response=>setTransaction(response.data))
}
else{
console.log(2)
adminFetcher.get("blockchain/history/").then(response=>setTransaction(response.data))
}
}
let navigator = useNavigate()
const collator = new Intl.Collator('ru');
const data:DataTypeIE[] = []
const columns: ColumnsType<DataTypeIE> = [
{
title: 'Тип операции',
dataIndex: 'type',
key: 'type',
sorter: (a, b) => collator.compare(a.type, b.type),
render: text=><Tag color="green">
{text}
</Tag>
},
{
title: 'Отправитель',
dataIndex: 'user_from',
key: 'user_from',
sorter: (a, b) => collator.compare(a.user_from, b.user_from) ,
},
{
title: 'Получатель',
dataIndex: 'user_to',
key: 'user_to',
sorter: (a, b) => collator.compare(a.user_to, b.user_to) ,
},
{
title: 'Сумма',
dataIndex: 'amount',
key: 'amount',
render: text=><div>{ text} <img src="/rub.svg"></img></div>
},
]
transaction.forEach((el:any)=>{
data.push({
key: el.type,
type: el.type,
user_from: el.user_from,
user_to: el.user_to,
amount: el.amount,
} as DataTypeIE)
})
return(
<div className="addProduct">
{hr? <Header links={[
{
link:"/hr",
name:"События"
},
{
link:"/hr/addEvent",
name:"Создать событие"
},
{
link:"/hr/transaction",
name:"История транзакций"
}
]} name={"HR"}></Header>: <Header links={[
{
link:"/admin/users",
name:"Участники"
},
{
link:"/admin/market",
name:"Market place"
},
{
link:"/admin/market/add",
name:"Cоздать товар (NFT)"
},
{
link:"/admin/transaction",
name:"История транзакций"
},
]}
name={"Firesieht"}></Header>
}
<div className="addProductCard">
<div className="addProductH1">История транзакций</div>
<Button onClick={()=>navigator("/transaction")} className="btn1">Сделать перевод</Button>
<Table columns={columns} dataSource={data} />
<Button onClick={()=>navigator(-1)} className="btn2">Назад</Button>
</div>
</div>
);
}

View File

@ -23,6 +23,12 @@ import { AdminClans } from './admin/adminClans';
import { AddUser } from './admin/addUser';
import { UserLk } from './user/lk';
import { Clan } from './user/clan';
import { HR } from './hr';
import { hrStore } from './app/hrStore';
import { AddEvent } from './hr/addEvent';
import { RegUsers } from './hr/regUsers';
import { TransactionHistory } from './hr/transactionHistory';
import { Transaction } from './Transaction';
import { ClanWar } from './user/clanWar';
import { Leaderboard } from './user/leaderboard';
import { Marketplace } from './user/marketplace';
@ -42,7 +48,16 @@ const router = createBrowserRouter(
<Route path='admin/users/:tg' element={<Provider store={adminStore}><AdminUserCard></AdminUserCard></Provider>}></Route>
<Route path='admin/clans/:id' element={<Provider store={adminStore}><AdminClans></AdminClans></Provider>}></Route>
<Route path='admin/users/add' element={<Provider store={adminStore}><AddUser></AddUser></Provider>}></Route>
<Route path="/admin/transaction" element={<Provider store={adminStore}><TransactionHistory></TransactionHistory></Provider>}></Route>
<Route path="hr" element={<Provider store={hrStore}><HR></HR></Provider>}></Route>
<Route path="hr/addEvent" element={<Provider store={hrStore}><AddEvent></AddEvent></Provider>}></Route>
<Route path="/hr/events/reg/:name" element={<Provider store={hrStore}><RegUsers></RegUsers></Provider>}></Route>
<Route path="/hr/transaction" element={<Provider store={hrStore}><TransactionHistory></TransactionHistory></Provider>}></Route>
<Route path="user/lk/" element={<UserLk />} />
<Route path='user/clan' element={<Clan />} />
<Route path="transaction" element={<Transaction></Transaction>}></Route>
<Route path="hr"></Route>
<Route path="user/events/" element={<UserLk />} />
<Route path='user/clan' element={<Clan />} />