-
-
-
-
{props.cost}
+
+
+
+
+
{props.cost}
+
+
{props.name}
+
{props.description.split(" ").slice(0,6).join(" ")}
+
+
-
{props.name}
-
{props.description}
-
-
+
)
}
\ No newline at end of file
diff --git a/src/admin/adminMarketPopUp/adminMarketPopUp.css b/src/admin/adminMarketPopUp/adminMarketPopUp.css
index 8ab03ed..564fea1 100644
--- a/src/admin/adminMarketPopUp/adminMarketPopUp.css
+++ b/src/admin/adminMarketPopUp/adminMarketPopUp.css
@@ -1,7 +1,7 @@
.changeProduct{
padding-top: 200px;
width: 100%;
- height: 100vh;
+ min-height: 100vh;
background: linear-gradient(85.91deg, #096DD9 0%, #40A9FF 100%);
display: flex;
flex-direction: column;
diff --git a/src/admin/adminMarketPopUp/index.tsx b/src/admin/adminMarketPopUp/index.tsx
index 67d68ed..bb8aaed 100644
--- a/src/admin/adminMarketPopUp/index.tsx
+++ b/src/admin/adminMarketPopUp/index.tsx
@@ -11,7 +11,7 @@ import { Header } from "../../components/Header"
export const AdminMarketPopUp:React.FC = () =>{
let {id} = useParams()
- let product = useAppSelector((state: RootAdminState)=>getProductByID(state, Number(id)))
+ let product = useAppSelector((state: RootAdminState)=>getProductByID(state, id as string))
const [cost, setCost] = useState(product.cost)
const [name, setName] = useState(product.name)
const [descr, setDescr] = useState(product.description)
@@ -23,10 +23,9 @@ export const AdminMarketPopUp:React.FC = () =>{
fetchChangeProduct(dispatch, {
cost: cost,
name: name,
- description: descr,
- id:product.id,
- image: product.image
- } as ProductIE)
+ descr: descr,
+ id: product.id
+ })
navigate("/admin/market")
}
diff --git a/src/admin/adminUserCard/adminUserCard.css b/src/admin/adminUserCard/adminUserCard.css
new file mode 100644
index 0000000..00621bf
--- /dev/null
+++ b/src/admin/adminUserCard/adminUserCard.css
@@ -0,0 +1,34 @@
+.userCard{
+ padding-top: 200px;
+ width: 100%;
+ min-height: 100vh;
+ background: linear-gradient(85.91deg, #096DD9 0%, #40A9FF 100%);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.userCardWrapper{
+ display: flex;
+ flex-direction: column;
+ gap:15px;
+ justify-content: flex-start;
+ align-items: flex-start;
+}
+
+.nameText{
+ font-weight: 400;
+ font-size: 16px;
+ line-height: 24px;
+ color: rgba(0, 0, 0, 0.85)
+}
+.fieldText{
+ font-size: 14px;
+ line-height: 22px;
+ color: rgba(0, 0, 0, 0.45);
+}
+.btnWrapper{
+ display: flex;
+ flex-direction: row;
+ gap: 25px
+}
\ No newline at end of file
diff --git a/src/admin/adminUserCard/index.tsx b/src/admin/adminUserCard/index.tsx
new file mode 100644
index 0000000..7efff1b
--- /dev/null
+++ b/src/admin/adminUserCard/index.tsx
@@ -0,0 +1,84 @@
+import { Button, Input } from "antd";
+import React, { useState } from "react";
+import { useNavigate, useParams } from "react-router-dom";
+import { fetchChangeEmployer, fetchDelEmployer, getEmployerByTg } from "../../app/admin/adminSlice";
+import { RootAdminState } from "../../app/adminStore";
+import { useAppDispatch, useAppSelector } from "../../app/hooks";
+import "./adminUserCard.css"
+
+export const AdminUserCard:React.FC = () => {
+ let {tg} = useParams()
+ let user = useAppSelector((state: RootAdminState) => getEmployerByTg(state, tg as string))
+ let dispatch = useAppDispatch()
+ let navigate = useNavigate()
+
+ const [name, setName] = useState(user.name)
+ const [balance, setbalance] = useState(user.balance)
+ const [respect, setrespect] = useState(user.respect)
+ const [command, setcommand] = useState(user.name)
+ const [jobTittle, setjobTittle] = useState(user.jobTittle)
+
+
+ const onDelete = () =>{
+ fetchDelEmployer(dispatch, user.telegramID)
+ }
+
+ const onSave = () =>{
+ fetchChangeEmployer(dispatch,{
+ name:name,
+ balance:balance,
+ respect: respect,
+ speciality: jobTittle,
+ tg:user.telegramID
+ })
+ alert("Данные сохранены!")
+ navigate("/admin/users")
+ }
+ return(
+
+
+
+ Редактирование пользователя: {user.name}
+
+
+
+
Telegram
+
{user.telegramID}
+
+
+
Кошелек
+
{user.wallet}
+
+
+
+
ФИО
+
setName(e.target.value)} placeholder="ФИО">
+
+
+
Баланс
+
setbalance(Number(e.target.value))} placeholder="баланс">
+
+
+
Респект
+
setrespect(Number(e.target.value))} placeholder="респект">
+
+
+
Команда
+
setcommand(e.target.value)} placeholder="команда">
+
+
+
Специальность
+
setjobTittle(e.target.value)} placeholder="специальность">
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/admin/index.tsx b/src/admin/index.tsx
index 624a983..3bc544b 100644
--- a/src/admin/index.tsx
+++ b/src/admin/index.tsx
@@ -8,21 +8,8 @@ import { RootAdminState } from "../app/adminStore";
import { Header } from "../components/Header";
export const AdminPage:React.FC = () => {
- const [respProducts, setRespProducts] = useState([-1 as any])
- let products = useAppSelector((state:RootAdminState)=>getProducts(state))
- let user = useAppSelector((state:RootAdminState)=>getUser(state))
- let dispatch = useAppDispatch()
- if (products.length == 0){
- adminFetcher.get("marketplace/product/").then(
- (response)=> setRespProducts(response.data as any)
- )
- }
- if (respProducts[0] != -1){
- respProducts.forEach((product)=>{
- fetchAddProduct(dispatch, product)
- })
- }
+ let user = useAppSelector((state:RootAdminState)=>getUser(state))
return(
diff --git a/src/admin/userTable/index.tsx b/src/admin/userTable/index.tsx
new file mode 100644
index 0000000..a9921d1
--- /dev/null
+++ b/src/admin/userTable/index.tsx
@@ -0,0 +1,225 @@
+import { Button, Space, Table, Tag } from 'antd';
+import type { ColumnsType } from 'antd/es/table';
+import React, { useReducer, useState } from 'react';
+import { Link, useNavigate } from 'react-router-dom';
+import { clearScreenDown } from 'readline';
+import { getClans, getEmployers, getUser, setClans, setEmployers } from '../../app/admin/adminSlice';
+import { RootAdminState } from '../../app/adminStore';
+import { adminFetcher, useAppDispatch, useAppSelector } from '../../app/hooks';
+import { ClanIE, EmployerIE } from '../../app/interfaces';
+import { Header } from '../../components/Header';
+import "./userTable.css"
+
+interface DataTypeIE{
+ key:string,
+ name:string,
+ telegram:string,
+ command:string,
+ respect:number,
+ balance:number,
+ speciality: string,
+}
+interface ClanColumnsIE{
+ key: string,
+ name: string,
+ tg: string,
+ members: number
+}
+
+
+export const UserTable:React.FC = () =>{
+ let [clans, setclans] = useState(false)
+
+ let navigator = useNavigate()
+ const collator = new Intl.Collator('ru');
+ let user = useAppSelector((state:RootAdminState)=>getUser(state))
+ const clanColums:ColumnsType
= [
+ {
+ title: "+",
+ key: "action",
+ render: (_, record) =>(
+ navigator("/admin/clans/" + record.name)} src="/gear.svg">
+ )
+ },
+ {
+ title: 'Название клана',
+ dataIndex: 'name',
+ key: 'name',
+ defaultSortOrder: 'descend',
+ sorter: (a, b) => collator.compare(a.name, b.name) ,
+ },
+ {
+ title: 'Telegram клана',
+ dataIndex: 'name',
+ key: 'name',
+ render: (_, record) => (@{record.name.split(" ").join("")}
),
+ sorter: (a, b) => collator.compare(a.name, b.name) ,
+ },
+ {
+ title: 'Количество участников',
+ dataIndex: 'members',
+ key: 'members',
+ sorter: (a, b) => a.members - b.members ,
+ },
+ {
+ title: 'Участники',
+ dataIndex: 'members',
+ key: 'members',
+ render: (_, record) => (Посмотреть
),
+ sorter: (a, b) => collator.compare(a.name, b.name) ,
+ },
+ ]
+ const columns: ColumnsType = [
+ {
+ title: "+",
+ key: "action",
+ render: (_, record) =>(
+ navigator("/admin/users/" + record.key)} src="/gear.svg">
+ )
+ },
+ {
+ title: 'ФИО',
+ dataIndex: 'name',
+ key: 'name',
+ defaultSortOrder: 'descend',
+ sorter: (a, b) => collator.compare(a.name, b.name) ,
+ },
+ {
+ title: 'Telegram',
+ dataIndex: 'telegram',
+ key: 'telegram',
+ sorter: (a, b) => collator.compare(a.telegram, b.telegram) ,
+
+ },
+ {
+ title: 'Название клана',
+ dataIndex: 'command',
+ key: 'command',
+ sorter: (a, b) => Number(a.command) - Number(b.command) ,
+
+ },
+ {
+ title: 'Респект',
+ dataIndex: 'respect',
+ key: 'respect',
+ sorter: (a, b) => a.respect - b.respect,
+ render: text=>{text + " "}
+ },
+ {
+ title: 'Баланс',
+ dataIndex: 'balance',
+ key: 'balance',
+ sorter: (a, b) => a.balance - b.balance,
+
+ render: text=>{text + " "}
+ },
+ {
+ title: 'Специальность',
+ dataIndex: 'speciality',
+ key: 'speciality',
+ sorter: (a, b) => collator.compare(a.speciality, b.speciality) ,
+ render: text=>
+ {text}
+
+ },
+ ]
+
+ let dispatch = useAppDispatch()
+
+ const data:DataTypeIE[] = []
+ const clanData:ClanColumnsIE[] = []
+
+ let users = useAppSelector((state:RootAdminState)=>getEmployers(state))
+ let clansData = useAppSelector((state:RootAdminState)=>getClans(state))
+ if (users.length == 0){
+ adminFetcher.get("users/").then((response)=>{
+ dispatch(setEmployers(response.data.map(((user:any)=>({
+ name: user.name,
+ wallet: user.wallet_public_key,
+ telegramID: user.telegram,
+ command: user.command,
+ role: user.type,
+ respect: user.respect,
+ balance: user.salary,
+ jobTittle: user.department,
+ clan: user.clan_name
+ }) as EmployerIE ))))
+ })
+ adminFetcher.get("season/clans/").then((response:any)=>{
+ dispatch(setClans(
+ response.data.map((clan:any)=>({
+ name: clan.name,
+ users: clan.users.map(((user:any)=>({
+ name: user.name,
+ wallet: user.wallet_public_key,
+ telegramID: user.telegram,
+ command: user.command,
+ role: user.type,
+ respect: user.respect,
+ balance: user.salary,
+ jobTittle: user.department,
+ }) ))
+ } as ClanIE))
+ ))
+ })
+ }
+ if (users.length > 0){
+ users.forEach((user)=>{
+ data.push(
+ {
+ name: user.name,
+ balance: user.balance,
+ command: user.clan,
+ speciality: user.jobTittle,
+ key: user.telegramID,
+ telegram: user.telegramID,
+ respect: user.respect,
+ } as DataTypeIE
+ )
+ })
+ clansData.forEach((clan)=>{
+ clanData.push({
+ key:clan.name,
+ name:clan.name,
+ tg: clan.name,
+ members:clan.users.length
+ } as ClanColumnsIE)
+ })
+ }
+
+ return(
+
+
+
+
Участники VTB Games
+
+
+
+
+
+
+
+
+ {
+ clans?
:
+ }
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/admin/userTable/userTable.css b/src/admin/userTable/userTable.css
new file mode 100644
index 0000000..a2e6885
--- /dev/null
+++ b/src/admin/userTable/userTable.css
@@ -0,0 +1,17 @@
+.userTable{
+ padding-top: 200px;
+ width: 100%;
+ min-height: 100vh;
+ background: linear-gradient(85.91deg, #096DD9 0%, #40A9FF 100%);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.userTableWrapper{
+ display: flex;
+ flex-direction: column;
+ gap:15px;
+ justify-content: flex-start;
+ align-items: flex-start;
+}
\ No newline at end of file
diff --git a/src/app/admin/adminSlice.ts b/src/app/admin/adminSlice.ts
index 88c0780..fd5904d 100644
--- a/src/app/admin/adminSlice.ts
+++ b/src/app/admin/adminSlice.ts
@@ -1,9 +1,10 @@
import { createAsyncThunk, createSlice, createSelector, PayloadAction } from '@reduxjs/toolkit'
import { stat } from 'fs'
-import { Market, Roles, SortTypes, UserIE, ProductIE} from '../interfaces'
+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'
@@ -13,14 +14,16 @@ const initState = {
user: {
wallet:"123214",
balance: 100,
- id:1,
+ id:"1",
role:Roles.admin,
name:"Firesieht"
} as UserIE, //потом достается запросом
market: {
sortType: SortTypes.sortByPriceSmaller,
products: []
- } as Market // потом достается запросом
+ } as Market, // потом достается запросом
+ employers: [] as EmployerIE[],
+ clans: [] as ClanIE[]
}
const adminSlice = createSlice(
@@ -28,13 +31,42 @@ const adminSlice = createSlice(
name: "adminSlice",
initialState: initState,
reducers:{
+ setClans(state, action:PayloadAction){
+ state.clans = action.payload
+ },
+ setEmployers(state, action:PayloadAction){
+ state.employers = action.payload
+ },
+ addEmployer(state, action:PayloadAction){
+ if(state.employers.length == 0){
+ state.employers = state.employers.concat([action.payload])
+ }
+ },
+ delEmployer(state, action:PayloadAction){
+ let employers = state.employers
+ let ind = 0
+ employers.forEach((employer, index)=>{
+ if (employer.telegramID == action.payload){
+ ind = index
+ }
+ })
+ employers.splice(ind, 1)
+ state.employers = employers
+ },
sendCoins(state, action: PayloadAction){
state.user.balance = state.user.balance - action.payload
},
addProduct(state, action: PayloadAction){
- state.market.products = state.market.products.concat([action.payload])
+ if(state.market.products.indexOf(action.payload) == -1){
+ state.market.products = state.market.products.concat([action.payload])
+ }
},
- delProduct(state, action:PayloadAction){
+ addProducts(state, action: PayloadAction){
+ if(state.market.products.length == 0){
+ state.market.products = state.market.products.concat(action.payload)
+ }
+ },
+ delProduct(state, action:PayloadAction){
let products = state.market.products
let ind = 0
products.forEach((product, index)=>{
@@ -45,6 +77,15 @@ const adminSlice = createSlice(
products.splice(ind, 1)
state.market.products = products
},
+ changeEmployer(state, action:PayloadAction){
+ let employers = state.employers
+ employers.forEach((product,index)=>{
+ if (product.telegramID == action.payload.telegramID){
+ employers[index] = action.payload
+ }
+ })
+ state.employers = employers
+ },
changeProduct(state, action:PayloadAction){
let products = state.market.products
products.forEach((product,index)=>{
@@ -64,29 +105,99 @@ export async function fetchSendCoins(dispatch:AppAdminDispatch, params:{userID:n
dispatch(sendCoins(params.amount))
}
-export async function fetchAddProduct(dispatch:AppAdminDispatch, params:{image: FormData, descr: string, name:string, cost:number}) {
+export async function fetchAddProduct(dispatch:AppAdminDispatch, params:{image: File, descr: string, name:string, cost:number}) {
//тут идет фетч
- let data = {
- image: "",
- description: params.descr,
- name: params.name,
- cost: params.cost,
- id: params.cost
- } as ProductIE //vмоковая даата
- adminFetcher.post("marketplace/product/", {
+ const formData = new FormData()
+ formData.append("name",params.name)
+ formData.append("description",params.descr)
+ formData.append("image", params.image)
+ formData.append("price",params.cost.toString())
+ adminFetcher.post("marketplace/product/", formData).then((response)=>{
+ dispatch(addProduct({
+ name: response.data.name,
+ description:response.data.description,
+ image: response.data.image_cropped,
+ cost:Number(response.data.price),
+ id:response.data.slug
+ } as ProductIE))
})
- dispatch(addProduct(data))
+
}
-export async function fetchDelProduct(dispatch:AppAdminDispatch, id:number) {
+export async function fetchDelProduct(dispatch:AppAdminDispatch, id:string) {
//тут идет фетч
- dispatch(delProduct(id))
+ adminFetcher.delete("marketplace/product/"+id).then(()=>dispatch(delProduct(id)))
+
}
-export async function fetchChangeProduct(dispatch:AppAdminDispatch, params:ProductIE) {
- dispatch(changeProduct(params))
+export async function fetchChangeProduct(dispatch:AppAdminDispatch, params:{id:string, descr: string, name:string, cost:number}) {
+ const formData = new FormData()
+ formData.append("name",params.name)
+ formData.append("description",params.descr)
+ formData.append("price",params.cost.toString())
+ adminFetcher.patch("marketplace/product/" + params.id, formData).then((response)=>{
+ dispatch(delProduct(params.id))
+ dispatch(addProduct({
+ name: response.data.name,
+ description:response.data.description,
+ image: response.data.image_cropped,
+ cost:Number(response.data.price),
+ id:response.data.slug
+ } as ProductIE))
+
+ })
+
+}
+
+export async function fetchAddEmployer(dispatch:AppAdminDispatch, params:{pass:string, name: string, respect: string, salary:string, command:string, tg:string, type: string}) {
+ const formData = new FormData()
+ formData.append("name",params.name)
+ formData.append("type",params.type)
+ formData.append("respect", params.respect.toString())
+ formData.append("salary",params.salary.toString())
+ formData.append("telegram",params.tg)
+ formData.append("command", params.command)
+ formData.append("password", params.pass)
+ adminFetcher.post("users/", formData).then((user)=>{
+ dispatch(addEmployer({
+ name: user.data.name,
+ wallet: user.data.wallet_public_key,
+ telegramID: user.data.telegram,
+ command: user.data.command,
+ role: user.data.type,
+ respect: user.data.respect,
+ balance: user.data.salary,
+ jobTittle: user.data.department,
+ } as EmployerIE))
+
+ })
+}
+
+export async function fetchDelEmployer(dispatch:AppAdminDispatch, tg:string) {
+ adminFetcher.delete("users/"+tg).then(()=>dispatch(delProduct(tg)))
+}
+
+export async function fetchChangeEmployer(dispatch:AppAdminDispatch, params:{name: string, respect: number, balance:number, speciality:string, tg:string}) {
+ const formData = new FormData()
+ formData.append("name",params.name)
+ formData.append("respect", params.respect.toString())
+ formData.append("salary",params.balance.toString())
+ adminFetcher.patch("users/" + params.tg, formData).then((user)=>{
+ console.log(user)
+ dispatch(changeEmployer({
+ name: user.data.name,
+ wallet: user.data.wallet_public_key,
+ telegramID: user.data.telegram,
+ command: user.data.command,
+ role: user.data.type,
+ respect: user.data.respect,
+ balance: user.data.salary,
+ jobTittle: user.data.department,
+ } as EmployerIE))
+
+ })
}
export const getProducts = createSelector(
@@ -95,7 +206,12 @@ export const getProducts = createSelector(
)
export const getProductByID = createSelector(
- (state:RootAdminState, id:number) => state.adminSlice.market.products.filter((product)=>product.id == id)[0],
+ (state:RootAdminState, id:string) => state.adminSlice.market.products.filter((product)=>product.id == id)[0],
+ (field)=>field
+)
+
+export const getEmployerByTg = createSelector(
+ (state:RootAdminState, tg:string) => state.adminSlice.employers.filter((product)=>product.telegramID == tg)[0],
(field)=>field
)
@@ -107,12 +223,30 @@ export const getUser = createSelector(
(state:RootAdminState) => state.adminSlice.user,
(field)=>field
)
+export const getEmployers = createSelector(
+ (state:RootAdminState) => state.adminSlice.employers,
+ (field)=>field
+)
+export const getClans = createSelector(
+ (state:RootAdminState) => state.adminSlice.clans,
+ (field)=>field
+)
+export const getClanByName = createSelector(
+ (state:RootAdminState, name: string) => state.adminSlice.clans.filter((clan)=>clan.name == name)[0],
+ (field)=>field
+)
export const {
sendCoins,
addProduct,
delProduct,
changeProduct,
+ addProducts,
+ setEmployers,
+ addEmployer,
+ delEmployer,
+ changeEmployer,
+ setClans
} = adminSlice.actions
export default adminSlice.reducer
\ No newline at end of file
diff --git a/src/app/hooks.ts b/src/app/hooks.ts
index 350cd1c..4ea28b1 100644
--- a/src/app/hooks.ts
+++ b/src/app/hooks.ts
@@ -9,7 +9,7 @@ export const useAppSelector: TypedUseSelectorHook = useSelector;
export const adminFetcher = axios.create(
{
baseURL: host,
- timeout: 1000,
+ timeout: 5000,
headers: {
Authorization: 'Bearer ' + token
}
diff --git a/src/app/interfaces.ts b/src/app/interfaces.ts
index e65eb84..3a9b021 100644
--- a/src/app/interfaces.ts
+++ b/src/app/interfaces.ts
@@ -14,7 +14,6 @@ export enum Specialities{
export interface UserIE{
wallet:string,
- id:number
role:Roles
balance: number,
name:string,
@@ -23,8 +22,11 @@ export interface UserIE{
export interface EmployerIE extends UserIE{
- jobTittle:Specialities,
+ jobTittle:string,
respect: number,
+ telegramID: string,
+ command: string,
+ clan:string
}
@@ -42,7 +44,7 @@ export interface ProductIE{
description:string,
image: string,
cost: number,
- id: number,
+ id: string,
}
export enum SortTypes{
@@ -55,3 +57,8 @@ export interface Market{
sortType: SortTypes,
products: ProductIE[],
}
+
+export interface ClanIE{
+ name:string,
+ users:UserIE[]
+}
\ No newline at end of file
diff --git a/src/components/Header/Header.css b/src/components/Header/Header.css
index c0238e8..df86e6e 100644
--- a/src/components/Header/Header.css
+++ b/src/components/Header/Header.css
@@ -15,6 +15,7 @@
line-height: 24px;
overflow: visible;
color: #FFFFFF;
+ z-index: 1000;
}
.links{
overflow: visible;
diff --git a/src/components/fileUploader.tsx b/src/components/fileUploader.tsx
index 530b36a..9d1c836 100644
--- a/src/components/fileUploader.tsx
+++ b/src/components/fileUploader.tsx
@@ -12,29 +12,25 @@ export const FileUploader:React.FC = (data) =>{
const props = {
name: 'file',
+ action: "",
headers: {
"content-type": 'multipart/form-data; boundary=----WebKitFormBoundaryqTqJIxvkWFYqvP5s'
},
- onChange(info:any) {
- if (info.file.status !== 'uploading') {
- }
-
- if (info.file.status === 'done') {
- data.onResponse(info.file.response)
- message.success(`${info.file.name} file uploaded successfully`);
- } else if (info.file.status === 'error') {
- message.error(`${info.file.name} file upload failed.`);
+ beforeUpload: (file:File) => {
+ const isPNG = file.type === 'image/png';
+ if (!isPNG) {
+ message.error(`${file.name} is not a png file`);
}
+ data.onResponse(file)
+ return isPNG || Upload.LIST_IGNORE;
+
},
+
};
return (
- {
- console.log(file);
- }} onDownload={(file) => {
- console.log(file)
- }} multiple>
-
+
+
);
}
\ No newline at end of file
diff --git a/src/index.tsx b/src/index.tsx
index 5befa93..2a4b55c 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -17,9 +17,14 @@ import {
Link,
Routes,
} from "react-router-dom";
+import { UserTable } from './admin/userTable';
+import { AdminUserCard } from './admin/adminUserCard';
+import { AdminClans } from './admin/adminClans';
+import { AddUser } from './admin/addUser';
import { UserLk } from './user/lk';
import { Clan } from './user/clan';
+
const container = document.getElementById('root')!;
const root = createRoot(container);
const router = createBrowserRouter(
@@ -29,6 +34,11 @@ const router = createBrowserRouter(
}>
}>
}>
+ }>
+ }>
+ }>
+ }>
+
} />
} />