Fixed somethind and added modal filtering
This commit is contained in:
commit
96a3c8e40b
|
@ -7,4 +7,5 @@ src/database/prisma/client
|
|||
*.sqlite
|
||||
package-lock.json
|
||||
.vscode
|
||||
*.db*
|
||||
*.db*
|
||||
db.json
|
|
@ -317,12 +317,12 @@
|
|||
}
|
||||
],
|
||||
"wagonTypeList": [
|
||||
"HalfCarriage",
|
||||
"Platform",
|
||||
"CoveredCarriage",
|
||||
"UsoPlatform",
|
||||
"Hopper",
|
||||
"Tank"
|
||||
["HalfCarriage","Полувагон"],
|
||||
["Platform","Платформа"],
|
||||
["CoveredCarriage","Крытый вагон"],
|
||||
["UsoPlatform","Платформа УСО"],
|
||||
["Hopper","Хоппер"],
|
||||
["Tank","Цистерна"]
|
||||
],
|
||||
"ownersList": [
|
||||
"НТС",
|
||||
|
|
|
@ -7,7 +7,7 @@ import prittierConfig from 'eslint-plugin-prettier/recommended.js';
|
|||
import react from 'eslint-plugin-react';
|
||||
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
|
||||
import globals from 'globals';
|
||||
|
||||
import reactHooksPlugin from 'eslint-plugin-react-hooks';
|
||||
/** @type { import("eslint").Linter.FlatConfig[] } */
|
||||
export default [
|
||||
{
|
||||
|
@ -52,11 +52,20 @@ export default [
|
|||
'import/no-named-as-default-member': 'warn',
|
||||
'import/no-duplicates': 'warn',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'unicorn/filename-case': [
|
||||
'error',
|
||||
{
|
||||
case: 'camelCase',
|
||||
},
|
||||
],
|
||||
'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks
|
||||
'react-hooks/exhaustive-deps': 'warn', // Checks effect dependencies
|
||||
},
|
||||
plugins: {
|
||||
'@typescript-eslint': typescript,
|
||||
react,
|
||||
import: importPlugin,
|
||||
'react-hooks': reactHooksPlugin,
|
||||
},
|
||||
},
|
||||
importPlugin.configs.typescript,
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
"author": "",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@remix-run/dev": "^2.4.0",
|
||||
"@remix-run/dev": "^2.4.1",
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"@types/eslint": "^8.56.0",
|
||||
"@types/node": "^18.19.3",
|
||||
|
@ -35,6 +35,7 @@
|
|||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-prettier": "^5.1.0",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-unicorn": "github:sindresorhus/eslint-plugin-unicorn",
|
||||
"lodash": "^4.17.21",
|
||||
"prettier": "3.1.1",
|
||||
|
@ -44,9 +45,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@nextui-org/react": "^2.2.9",
|
||||
"@remix-run/node": "^2.4.0",
|
||||
"@remix-run/react": "^2.4.0",
|
||||
"@remix-run/serve": "^2.4.0",
|
||||
"@remix-run/node": "^2.4.1",
|
||||
"@remix-run/react": "^2.4.1",
|
||||
"@remix-run/serve": "^2.4.1",
|
||||
"bcrypt": "^5.1.1",
|
||||
"framer-motion": "^10.16.16",
|
||||
"isbot": "^3.7.1",
|
||||
|
|
|
@ -1,23 +1,27 @@
|
|||
import type { IStation } from 'app/services/api/interfaces.server';
|
||||
import React from 'react';
|
||||
import {Select, SelectSection, SelectItem} from "@nextui-org/react";
|
||||
import { Select, SelectSection, SelectItem } from '@nextui-org/react';
|
||||
|
||||
export default function ControlFormHeader({Stations}: {Stations: IStation[]}) {
|
||||
return(
|
||||
export default function ControlFormHeader({
|
||||
Stations,
|
||||
}: {
|
||||
Stations: IStation[];
|
||||
}) {
|
||||
return (
|
||||
<div id="control-form-header" className="flex gap-4">
|
||||
<Select
|
||||
label="Station filter"
|
||||
placeholder="Select a station"
|
||||
selectionMode="multiple"
|
||||
className="w-[250px]"
|
||||
size='sm'
|
||||
>
|
||||
size="sm"
|
||||
>
|
||||
{Stations.map((station) => (
|
||||
<SelectItem key={station.title} value={station.title}>
|
||||
{station.title}
|
||||
{station.title}
|
||||
</SelectItem>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
export default function controlTable() {
|
||||
return(
|
||||
<div id="control-table">
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return <div id="control-table"></div>;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,307 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
Modal,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
Button,
|
||||
useDisclosure,
|
||||
Listbox,
|
||||
ListboxItem,
|
||||
Select,
|
||||
SelectItem,
|
||||
} from '@nextui-org/react';
|
||||
import { IStationData } from 'app/services/api/interfaces.server';
|
||||
import { useSearchParams, useNavigate } from '@remix-run/react';
|
||||
|
||||
type Tdb = {
|
||||
stationsData: IStationData[];
|
||||
ownersList: string[];
|
||||
wagonTypeList: string[][];
|
||||
};
|
||||
|
||||
type Tfilters = {
|
||||
[filterKey: string]: {
|
||||
title: string;
|
||||
items: { key: string; value: string }[];
|
||||
};
|
||||
};
|
||||
|
||||
const filterMenuKeys: Record<string, string> = {
|
||||
wagons: 'Вагоны',
|
||||
ways: 'Ж/Д Пути',
|
||||
stations: 'Станции',
|
||||
};
|
||||
|
||||
function getFilterSelectedKeys(searchParameters: URLSearchParams) {
|
||||
const result: {
|
||||
[filterMenuKey: string]: { [filterKey: string]: Set<string> };
|
||||
} = {};
|
||||
const _filters = [...searchParameters.entries()]
|
||||
.filter((parameter) => parameter[0].startsWith('filter'))
|
||||
.map((parameter) => [parameter[0].replace('filter', ''), parameter[1]]);
|
||||
for (const [name, value] of _filters) {
|
||||
const [filterMenuKey, filterKey] = name
|
||||
.match(/[A-Z][a-z]*/g)!
|
||||
.map((value_) => value_.toLowerCase());
|
||||
if (!(filterMenuKey in result)) {
|
||||
result[filterMenuKey] = {};
|
||||
}
|
||||
result[filterMenuKey][filterKey] = new Set(value.split(','));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function FilterMenu({
|
||||
activeFilterMenuKey,
|
||||
filters,
|
||||
statesSelectedKeys,
|
||||
}: {
|
||||
activeFilterMenuKey: string;
|
||||
filters: Tfilters;
|
||||
statesSelectedKeys: {
|
||||
[activeFilterMenuKey: string]: {
|
||||
[filterKey: string]: [
|
||||
Set<string>,
|
||||
React.Dispatch<React.SetStateAction<Set<string>>>,
|
||||
];
|
||||
};
|
||||
};
|
||||
}) {
|
||||
const [searchParameters] = useSearchParams();
|
||||
|
||||
const _t = getFilterSelectedKeys(searchParameters);
|
||||
for (const filterKey of Object.keys(filters)) {
|
||||
if (
|
||||
!(
|
||||
filterKey in
|
||||
Object.keys(statesSelectedKeys[activeFilterMenuKey])
|
||||
) &&
|
||||
!(activeFilterMenuKey in _t)
|
||||
) {
|
||||
_t[activeFilterMenuKey] = {};
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{Object.keys(filters).map((filterKey) => {
|
||||
return (
|
||||
<>
|
||||
<h4>{filters[filterKey].title}</h4>
|
||||
<Select
|
||||
aria-label="Один из пунктов фильтра"
|
||||
placeholder="Не выбрано"
|
||||
selectionMode="multiple"
|
||||
onChange={(event)=> {
|
||||
statesSelectedKeys[activeFilterMenuKey][
|
||||
filterKey
|
||||
][1](new Set(event.target.value.split(",")))
|
||||
}}
|
||||
selectedKeys={
|
||||
statesSelectedKeys[activeFilterMenuKey][
|
||||
filterKey
|
||||
][0]
|
||||
}
|
||||
onSelectionChange={(keys) =>
|
||||
(keys as Set<string>)
|
||||
}
|
||||
>
|
||||
{filters[filterKey].items.map((value) => {
|
||||
return (
|
||||
<SelectItem
|
||||
key={value.key}
|
||||
value={value.value}
|
||||
>
|
||||
{value.key}
|
||||
</SelectItem>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ModalFilter({ db }: { db: Tdb }) {
|
||||
const filters: { [filterMenuKey: string]: Tfilters } = {
|
||||
wagons: {
|
||||
owner: {
|
||||
title: 'Собственник',
|
||||
items: db.ownersList.map((owner) => {
|
||||
return { key: owner, value: owner };
|
||||
}),
|
||||
},
|
||||
state: {
|
||||
title: 'Состояние вагона',
|
||||
items: [
|
||||
{
|
||||
key: 'Не прибыл',
|
||||
value: 'NotArrived',
|
||||
},
|
||||
{
|
||||
key: 'Простаивает',
|
||||
value: 'StandingBy',
|
||||
},
|
||||
{
|
||||
key: 'Закончил',
|
||||
value: 'Finished',
|
||||
},
|
||||
{
|
||||
key: 'В работе',
|
||||
value: 'inProgress',
|
||||
},
|
||||
],
|
||||
},
|
||||
type: {
|
||||
title: 'Тип вагона',
|
||||
items: db.wagonTypeList.map((type) => {
|
||||
return { key: type[1], value: type[0] };
|
||||
}),
|
||||
},
|
||||
},
|
||||
ways: {
|
||||
empty: {
|
||||
title: 'Загруженность пути',
|
||||
items: [
|
||||
{
|
||||
key: 'Полная',
|
||||
value: 'full',
|
||||
},
|
||||
{
|
||||
key: 'Частичная',
|
||||
value: 'half',
|
||||
},
|
||||
{
|
||||
key: 'Отсутствует',
|
||||
value: 'empty',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
const [searchParameters] = useSearchParams();
|
||||
const navigate = useNavigate();
|
||||
const { isOpen, onOpen, onOpenChange } = useDisclosure();
|
||||
const [activeFilterMenuKey, setActiveFilterMenuKey] = React.useState(
|
||||
Object.keys(filterMenuKeys)[0],
|
||||
);
|
||||
const statesSelectedKeys: {
|
||||
[activeFilterMenuKey: string]: {
|
||||
[filterKey: string]: [
|
||||
Set<string>,
|
||||
React.Dispatch<React.SetStateAction<Set<string>>>,
|
||||
];
|
||||
};
|
||||
} = {};
|
||||
statesSelectedKeys[activeFilterMenuKey] = {};
|
||||
const _t = getFilterSelectedKeys(searchParameters);
|
||||
|
||||
for (const filterMenuKey in filters) {
|
||||
if (!(filterMenuKey in statesSelectedKeys)) {
|
||||
statesSelectedKeys[filterMenuKey] = {};
|
||||
}
|
||||
for (const filterKey in filters[filterMenuKey]) {
|
||||
/* eslint-disable-next-line */
|
||||
statesSelectedKeys[filterMenuKey][filterKey] = React.useState(
|
||||
_t[filterMenuKey] === undefined
|
||||
? new Set()
|
||||
: _t[filterMenuKey][filterKey] ?? new Set(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onPress={onOpen}>Фильтр</Button>
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onOpenChange={onOpenChange}
|
||||
scrollBehavior="outside"
|
||||
size="xl"
|
||||
>
|
||||
<ModalContent aria-label="Пользовательский фильтр">
|
||||
{(onClose) => (
|
||||
<>
|
||||
<ModalHeader>Пользовательский фильтр</ModalHeader>
|
||||
<ModalBody>
|
||||
<Listbox
|
||||
onAction={(menuKey) =>
|
||||
setActiveFilterMenuKey(
|
||||
menuKey.toString(),
|
||||
)
|
||||
}
|
||||
>
|
||||
{Object.keys(filterMenuKeys).map((key) => (
|
||||
<ListboxItem key={key}>
|
||||
{filterMenuKeys[key]}
|
||||
</ListboxItem>
|
||||
))}
|
||||
</Listbox>
|
||||
<div>
|
||||
<FilterMenu
|
||||
activeFilterMenuKey={
|
||||
activeFilterMenuKey
|
||||
}
|
||||
filters={filters[activeFilterMenuKey]}
|
||||
statesSelectedKeys={statesSelectedKeys}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => {
|
||||
for (const menuKey in statesSelectedKeys) {
|
||||
for (const filterKey in statesSelectedKeys[
|
||||
menuKey
|
||||
]) {
|
||||
const _m=Array.from(
|
||||
statesSelectedKeys[
|
||||
menuKey
|
||||
][
|
||||
filterKey
|
||||
][0].values()
|
||||
)
|
||||
if (
|
||||
_m[0] === '' || _m.length==0
|
||||
) {
|
||||
searchParameters.delete(
|
||||
`filter${
|
||||
menuKey[0].toUpperCase() +
|
||||
menuKey.slice(1)
|
||||
}${
|
||||
filterKey[0].toUpperCase() +
|
||||
filterKey.slice(1)
|
||||
}`,
|
||||
);
|
||||
} else {
|
||||
searchParameters.set(
|
||||
`filter${
|
||||
menuKey[0].toUpperCase() +
|
||||
menuKey.slice(1)
|
||||
}${
|
||||
filterKey[0].toUpperCase() +
|
||||
filterKey.slice(1)
|
||||
}`,
|
||||
_m.join(','),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
navigate(
|
||||
'?' + searchParameters.toString(),
|
||||
);
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
Применить
|
||||
</Button>
|
||||
<Button onClick={onClose}>Отмена</Button>
|
||||
</ModalBody>
|
||||
</>
|
||||
)}
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
import React from 'react';
|
||||
|
||||
export default function Park() {
|
||||
return(
|
||||
<div id="control-park">
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
import type { IStationData } from 'app/services/api/interfaces.server';
|
||||
import React from 'react';
|
||||
|
||||
export default function Station({StationData}: {StationData: IStationData}) {
|
||||
return(
|
||||
<div id="control-station">
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
export default function Park() {
|
||||
return <div id="control-park"></div>;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import type { IStationData } from 'app/services/api/interfaces.server';
|
||||
import React from 'react';
|
||||
|
||||
export default function Station({
|
||||
StationData,
|
||||
}: {
|
||||
StationData: IStationData;
|
||||
}) {
|
||||
return <div id="control-station"></div>;
|
||||
}
|
|
@ -1,30 +1,42 @@
|
|||
import React from 'react';
|
||||
import { json, type LoaderFunctionArgs } from '@remix-run/node';
|
||||
import { authenticator } from '../services/auth.server';
|
||||
import { IStation } from 'app/services/api/interfaces.server';
|
||||
import { IStation, IStationData } from 'app/services/api/interfaces.server';
|
||||
import { api } from 'app/services/api/json.api.server';
|
||||
import { useLoaderData } from '@remix-run/react';
|
||||
import ControlFormHeader from 'app/coms/controlFormHeader';
|
||||
import ModalFilter from 'app/coms/modalFilter';
|
||||
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
const authData = await authenticator.isAuthenticated(request, {
|
||||
failureRedirect: '/login',
|
||||
});
|
||||
const Stations: IStation[] = await api.getStations();
|
||||
const Owners: string[] = await api.getOwners();
|
||||
const stations: IStation[] = await api.getStations();
|
||||
const stationsData = await api.getStationsData();
|
||||
const owners: string[] = await api.getOwners();
|
||||
const wagonTypeList = await api.getWagonTypes();
|
||||
return json({
|
||||
Stations,
|
||||
Owners,
|
||||
stations,
|
||||
stationsData,
|
||||
owners,
|
||||
authData,
|
||||
wagonTypeList,
|
||||
});
|
||||
}
|
||||
|
||||
export default function Index() {
|
||||
const {authData, Stations, Owners} = useLoaderData<typeof loader>();
|
||||
console.log(Owners);
|
||||
const { authData, stations, owners, stationsData, wagonTypeList } =
|
||||
useLoaderData<typeof loader>();
|
||||
return (
|
||||
<div id="control-form" className='w-full h-full p-2 flex flex-col'>
|
||||
<ControlFormHeader Stations={Stations}/>
|
||||
<div id="control-form" className="w-full h-full p-2 flex flex-col">
|
||||
<ControlFormHeader Stations={stations} />
|
||||
<ModalFilter
|
||||
db={{
|
||||
stationsData: stationsData,
|
||||
ownersList: owners,
|
||||
wagonTypeList,
|
||||
}}
|
||||
></ModalFilter>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ export default function Auth() {
|
|||
placeholder="Enter your password"
|
||||
/>
|
||||
<Button type="submit" color="primary">
|
||||
{' '}
|
||||
Login
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -28,7 +28,6 @@ export default function Login() {
|
|||
placeholder="Enter your password"
|
||||
/>
|
||||
<Button type="submit" color="primary">
|
||||
{' '}
|
||||
Login
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
import fetch from 'node-fetch';
|
||||
import { env } from 'node:process';
|
||||
import { INorm, IOperationType, IStation, IStationData, IUser } from './interfaces.server';
|
||||
import {
|
||||
INorm,
|
||||
IOperationType,
|
||||
IStation,
|
||||
IStationData,
|
||||
IUser,
|
||||
} from './interfaces.server';
|
||||
|
||||
const endpoints = {
|
||||
getStations: 'stationsList',
|
||||
|
@ -9,11 +15,13 @@ const endpoints = {
|
|||
getOwnersList: 'ownersList',
|
||||
getNorms: 'operationsTypesNorms',
|
||||
getOperationsTypes: 'operationsTypes',
|
||||
getUsers:'users'
|
||||
getUsers: 'users',
|
||||
};
|
||||
|
||||
export const api = new (class ApiDB {
|
||||
private readonly url = `http://localhost:${(env.DB_PORT ?? 4000).toString()}/`;
|
||||
private readonly url = `http://localhost:${(
|
||||
env.DB_PORT ?? 4000
|
||||
).toString()}/`;
|
||||
constructor() {}
|
||||
async getStations(): Promise<IStation[]> {
|
||||
const response = await fetch(this.url + endpoints.getStations, {
|
||||
|
@ -37,7 +45,7 @@ export const api = new (class ApiDB {
|
|||
const response = await fetch(this.url + endpoints.getWagonTypeList, {
|
||||
method: 'GET',
|
||||
});
|
||||
return (await response.json()) as string[];
|
||||
return (await response.json()) as string[][];
|
||||
}
|
||||
async getOwners() {
|
||||
const response = await fetch(this.url + endpoints.getOwnersList, {
|
||||
|
@ -46,23 +54,39 @@ export const api = new (class ApiDB {
|
|||
return (await response.json()) as string[];
|
||||
}
|
||||
|
||||
async getStationData(stationID: number): Promise<IStationData[]> {
|
||||
async getStationData(stationID: number): Promise<IStationData> {
|
||||
const response = await fetch(
|
||||
this.url + endpoints.getStationsData + `?station.id=${stationID}`,
|
||||
{
|
||||
method: 'GET',
|
||||
},
|
||||
);
|
||||
return ((await response.json()) as IStationData[])[0];
|
||||
}
|
||||
async getStationsData(): Promise<IStationData[]> {
|
||||
const response = await fetch(this.url + endpoints.getStationsData, {
|
||||
method: 'GET',
|
||||
});
|
||||
return (await response.json()) as IStationData[];
|
||||
}
|
||||
async getUsers(){
|
||||
const response = await fetch(this.url + endpoints.getUsers,{method:"GET"});
|
||||
async getUsers() {
|
||||
const response = await fetch(this.url + endpoints.getUsers, {
|
||||
method: 'GET',
|
||||
});
|
||||
return (await response.json()) as IUser[];
|
||||
}
|
||||
async createUser(user:Omit<IUser,"id">){
|
||||
const response = await fetch(this.url + endpoints.getUsers,{method:"POST",headers:{
|
||||
"Content-Type": "application/json",
|
||||
},body:JSON.stringify(user)});
|
||||
return response.ok
|
||||
async createUser(user: Omit<IUser, 'id'>) {
|
||||
const response = await fetch(this.url + endpoints.getUsers, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(user),
|
||||
});
|
||||
if (response.ok) {
|
||||
return (await response.json()) as IUser;
|
||||
} else {
|
||||
throw new Error('Unknown answer from db');
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -5,7 +5,6 @@ import { hash, compare } from 'bcrypt';
|
|||
import { IUser } from './api/interfaces.server';
|
||||
import { api } from './api/json.api.server';
|
||||
|
||||
|
||||
export let authenticator = new Authenticator<IUser>(sessionStorage);
|
||||
const saltRounds = 9;
|
||||
|
||||
|
@ -13,26 +12,27 @@ authenticator.use(
|
|||
new FormStrategy(async ({ form }) => {
|
||||
let login = <string>form.get('login');
|
||||
let password = <string>form.get('password');
|
||||
const users=await api.getUsers();
|
||||
|
||||
const users = await api.getUsers();
|
||||
for (const user of users) {
|
||||
if (user.login==login && await compare(password,user.password)){
|
||||
if (
|
||||
user.login == login &&
|
||||
(await compare(password, user.password))
|
||||
) {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
throw new Error("Wrong credentials")
|
||||
|
||||
throw new Error('Wrong credentials');
|
||||
}),
|
||||
'user-login',
|
||||
);
|
||||
|
||||
authenticator.use(
|
||||
new FormStrategy(async ({ form, context }) => {
|
||||
new FormStrategy(async ({ form }) => {
|
||||
let login = <string>form.get('login');
|
||||
let password = <string>form.get('password');
|
||||
|
||||
let hashedPassword = '';
|
||||
await hash(password, saltRounds, (error, hash) => {
|
||||
hash(password, saltRounds, (error, hash) => {
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ authenticator.use(
|
|||
if (!hashedPassword) {
|
||||
throw '';
|
||||
}
|
||||
|
||||
const user = {id:4, login: 'null', password: 'null' };
|
||||
|
||||
const user = await api.createUser({ login, password: hashedPassword });
|
||||
|
||||
return user;
|
||||
}),
|
||||
|
|
Loading…
Reference in New Issue