Initial commit

This commit is contained in:
Kayashov.SM
2025-03-12 17:54:16 +04:00
commit b6d8a3cebd
254 changed files with 29963 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
import {createLogger} from "./Logger";
import {config} from "../Config";
export const logger = createLogger({ level: config.logLevel });

65
front/src/lib/Logger.js Normal file
View File

@@ -0,0 +1,65 @@
/* eslint-disable no-console -- Allow */
// NOTE: A tracking system such as Sentry should replace the console
export const LogLevel = {NONE: 'NONE', ERROR: 'ERROR', WARN: 'WARN', DEBUG: 'DEBUG', ALL: 'ALL'};
const LogLevelNumber = {NONE: 0, ERROR: 1, WARN: 2, DEBUG: 3, ALL: 4};
export class Logger {
prefix;
level;
showLevel;
levelNumber;
constructor({prefix = '', level = LogLevel.ALL, showLevel = true}) {
this.prefix = prefix;
this.level = level;
this.levelNumber = LogLevelNumber[this.level];
this.showLevel = showLevel;
}
debug = (...args) => {
if (this.canWrite(LogLevel.DEBUG)) {
this.write(LogLevel.DEBUG, ...args);
}
};
warn = (...args) => {
if (this.canWrite(LogLevel.WARN)) {
this.write(LogLevel.WARN, ...args);
}
};
error = (...args) => {
if (this.canWrite(LogLevel.ERROR)) {
this.write(LogLevel.ERROR, ...args);
}
};
canWrite(level) {
return this.levelNumber >= LogLevelNumber[level];
}
write(level, ...args) {
let prefix = this.prefix;
if (this.showLevel) {
prefix = `- ${level} ${prefix}`;
}
if (level === LogLevel.ERROR) {
console.error(prefix, ...args);
} else {
console.log(prefix, ...args);
}
}
}
// This can be extended to create context specific logger (Server Action, Router Handler, etc.)
// to add context information (IP, User-Agent, timestamp, etc.)
export function createLogger({prefix, level} = {}) {
return new Logger({prefix, level});
}

View File

@@ -0,0 +1,34 @@
import {decodeToken, isExpired} from "react-jwt";
import {requests} from "../requests";
import axios from "axios";
class TokenUtil {
checkToken(token) {
if (token == null || isExpired(token)) {
return false;
}
this.refreshToken();
return true;
}
getToken() {
return localStorage.getItem("token");
}
refreshToken() {
const decoded = decodeToken(this.getToken());
const currentTime = Date.now() / 1000;
if (decoded.exp - currentTime > 43200) {
return
}
axios.post(requests.auth.refresh, {}, {headers: {'Authorization': this.getToken()}})
.then((r) => {
localStorage.setItem("token", r.data.token)
})
}
}
export const tokenUtil = new TokenUtil();

View File

@@ -0,0 +1,9 @@
class AuthClient {
async signOut() {
localStorage.removeItem("token");
return {};
}
}
export const authClient = new AuthClient();

View File

@@ -0,0 +1,17 @@
import {requests} from "../../requests";
import {api} from "./api";
class UserClient {
async getMe() {
try{
let url = requests.users.getMe
const response = await api().get(url);
return {data: response.data}
} catch (e) {
return {errorData: e.data}
}
}
}
export const userClient = new UserClient();

View File

@@ -0,0 +1,16 @@
import axios from "axios";
import {tokenUtil} from "../TokenUtil";
// const host = "localhost:8080"; //дебаг вместе с беком
// const host = "192.168.1.100:8091"; //дебаг фронта
const host = "bar.kayashov.keenetic.pro"; //прод
export const api = () => {
const result = axios;
result.defaults.baseURL = `${window.location.protocol}//${host}/`;
if (tokenUtil.checkToken(tokenUtil.getToken())) {
result.defaults.headers.common["Authorization"] = "Bearer " + tokenUtil.getToken();
} else {
delete result.defaults.headers.common
}
return result;
}

View File

@@ -0,0 +1,11 @@
export function getSiteURL() {
let url =
process.env.NEXT_PUBLIC_SITE_URL ?? // Set this to your site URL in production env.
process.env.NEXT_PUBLIC_VERCEL_URL ?? // Automatically set by Vercel.
'http://localhost:3000/';
// Make sure to include `https://` when not localhost.
url = url.includes('http') ? url : `https://${url}`;
// Make sure to include a trailing `/`.
url = url.endsWith('/') ? url : `${url}/`;
return url;
}

View File

@@ -0,0 +1,25 @@
export function isNavItemActive({
disabled,
external,
href,
matcher,
pathname,
}) {
if (disabled || !href || external) {
return false;
}
if (matcher) {
if (matcher.type === 'startsWith') {
return pathname.startsWith(matcher.href);
}
if (matcher.type === 'equals') {
return pathname === matcher.href;
}
return false;
}
return pathname === href;
}

View File

@@ -0,0 +1,18 @@
export const sliceData = (rows, page, elementOnPage) => {
if (!rows || rows.length === 0) {
return [];
}
const maxPage = Math.ceil(rows.length / elementOnPage);
// const start = (page - 1) * elementOnPage;
const start = 0;
console.log(maxPage, start)
let end;
if (page === maxPage) {
end = rows.length;
} else {
end = start + elementOnPage;
}
return rows.slice(start, end);
}