initial commit
This commit is contained in:
4
front/src/lib/DefaultLogger.js
Normal file
4
front/src/lib/DefaultLogger.js
Normal 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
65
front/src/lib/Logger.js
Normal 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});
|
||||
}
|
||||
45
front/src/lib/clients/AuthClient.js
Normal file
45
front/src/lib/clients/AuthClient.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import {api} from "./api";
|
||||
import {requests} from "../../requests";
|
||||
|
||||
class AuthClient {
|
||||
|
||||
async signOut() {
|
||||
localStorage.removeItem("token");
|
||||
return {};
|
||||
}
|
||||
|
||||
async login(request, setLoading, setError, checkSession) {
|
||||
setLoading(true);
|
||||
const response = await api().post(requests.auth.login, request);
|
||||
|
||||
if (response.data.error) {
|
||||
setError(response.data.error);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.setItem("token", response.data.token);
|
||||
|
||||
await checkSession?.();
|
||||
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
loginByCode(code, checkSession) {
|
||||
const request = {
|
||||
byLogin: false,
|
||||
code: code
|
||||
}
|
||||
api().post(requests.auth.login, request)
|
||||
.then(async (response) => {
|
||||
if (response.data.error) {
|
||||
return;
|
||||
}
|
||||
localStorage.setItem("token", response.data.token);
|
||||
await checkSession?.();
|
||||
window.location.reload();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const authClient = new AuthClient();
|
||||
74
front/src/lib/clients/BarClient.js
Normal file
74
front/src/lib/clients/BarClient.js
Normal file
@@ -0,0 +1,74 @@
|
||||
import {api} from "./api";
|
||||
import {requests} from "../../requests";
|
||||
import {getComparator} from "../../components/core/getComparator";
|
||||
|
||||
class BarClient {
|
||||
|
||||
getBarList(setBars, createError) {
|
||||
api().get(requests.bar.all)
|
||||
.then((r) => {
|
||||
setBars(r.data.sort(getComparator("name")))
|
||||
})
|
||||
.catch(() => {
|
||||
createError("Ошибка получения списков")
|
||||
})
|
||||
}
|
||||
|
||||
changeBar(id, bars, createWarning, createSuccess, createError, setBars) {
|
||||
createWarning("Дождитесь окончания операции")
|
||||
api().post(`${requests.bar.change}/${id}`)
|
||||
.then(() => createSuccess("Список изменен"))
|
||||
.catch(() => createError("Ошибка изменения активного списка"))
|
||||
|
||||
const newState = bars.map((b) => {
|
||||
if (b.active) {
|
||||
return {
|
||||
...b, active: false
|
||||
}
|
||||
}
|
||||
if (b.id === id) {
|
||||
return {
|
||||
...b, active: true
|
||||
}
|
||||
}
|
||||
return b;
|
||||
})
|
||||
setBars(newState);
|
||||
}
|
||||
|
||||
deleteBar(bar, bars, createError, createSuccess, setBars) {
|
||||
if (bar.active) {
|
||||
createError("Нельзя удалить активный бар!")
|
||||
return;
|
||||
}
|
||||
api().delete(requests.bar.crud + bar.id)
|
||||
.then(() => createSuccess("Список удален"))
|
||||
.catch(() => createError("Ошибка удаления. Обновите страницу"))
|
||||
|
||||
setBars(bars.filter((b) => b.id !== bar.id));
|
||||
}
|
||||
|
||||
createBar(name, bars, createSuccess, createError, setBars, setOpen) {
|
||||
api().post(requests.bar.crud + name)
|
||||
.then((r) => {
|
||||
createSuccess("Cписок создан");
|
||||
let state = bars;
|
||||
state.push(r.data);
|
||||
setBars(state)
|
||||
setOpen(false)
|
||||
}).catch(() => createError("Ошибка создания списка"))
|
||||
}
|
||||
|
||||
copyBar(oldId, newName, setBars, bars, createError, createSuccess, setOpen) {
|
||||
api().post(requests.bar.crud + "copy/" + oldId + "/" + newName)
|
||||
.then((r) => {
|
||||
const state = bars;
|
||||
state.push(r.data)
|
||||
setBars(state);
|
||||
createSuccess("Бар скопирован")
|
||||
setOpen(false)
|
||||
}).catch(() => createError("Ошибка при копировании бара"))
|
||||
}
|
||||
}
|
||||
|
||||
export const barClient = new BarClient();
|
||||
19
front/src/lib/clients/CategoryClient.js
Normal file
19
front/src/lib/clients/CategoryClient.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import {api} from "./api";
|
||||
import {requests} from "../../requests";
|
||||
import {getComparator} from "../../components/core/getComparator";
|
||||
|
||||
class CategoryClient {
|
||||
|
||||
getCategoryList(setCategory, createError) {
|
||||
api().get(requests.category.basic)
|
||||
.then((r) => {
|
||||
setCategory(r.data.sort(getComparator())
|
||||
.map((item, i) => {
|
||||
return {id: i, name: item}
|
||||
}))
|
||||
})
|
||||
.catch(() => createError("Ошибка получения категорий"))
|
||||
}
|
||||
};
|
||||
|
||||
export const categoryClient = new CategoryClient();
|
||||
216
front/src/lib/clients/CocktailClient.js
Normal file
216
front/src/lib/clients/CocktailClient.js
Normal file
@@ -0,0 +1,216 @@
|
||||
import {api} from "./api";
|
||||
import {requests} from "../../requests";
|
||||
import {sortList} from "../../components/cocktails/sortingList";
|
||||
import {getComparator} from "../../components/core/getComparator";
|
||||
|
||||
class CocktailClient {
|
||||
emptyCocktailForEditPage = {
|
||||
id: null,
|
||||
name: "",
|
||||
alcoholic: "",
|
||||
category: "",
|
||||
components: "",
|
||||
glass: "",
|
||||
image: "",
|
||||
instructions: "",
|
||||
isAllowed: false,
|
||||
rating: {
|
||||
rating: 0,
|
||||
favourite: false
|
||||
},
|
||||
receipt: [],
|
||||
tags: "",
|
||||
video: ""
|
||||
}
|
||||
|
||||
getMenu(setRows, setIsNew, setPage, setLoad, setIsEnd, isNew, rows, page, size, filter, createError) {
|
||||
setLoad(true);
|
||||
|
||||
const request = {
|
||||
...filter,
|
||||
sort: sortList.find((s) => s.name === filter.sorting).id,
|
||||
page: page + 1,
|
||||
size: size,
|
||||
notHaveCount: Array.isArray(filter.iCount) ? null : filter.iCount
|
||||
}
|
||||
|
||||
api().post(requests.cocktails.menu, request)
|
||||
.then((r) => {
|
||||
if (r.data.length === 0) {
|
||||
if (isNew) {
|
||||
setRows([]);
|
||||
}
|
||||
setIsEnd(true);
|
||||
setLoad(false);
|
||||
return;
|
||||
}
|
||||
const cocktails = isNew ? r.data : rows.concat(r.data);
|
||||
setRows(cocktails);
|
||||
setIsNew(false);
|
||||
setPage(page + 1);
|
||||
setLoad(false);
|
||||
})
|
||||
.catch((r) => {
|
||||
setLoad(false);
|
||||
createError("Ошибка загрузки данных от сервера Status:" + r.code)
|
||||
})
|
||||
}
|
||||
|
||||
async getCocktailByIngredient(ingredient, setCocktails) {
|
||||
if(!ingredient) {
|
||||
return
|
||||
}
|
||||
api().get(requests.cocktails.byIngredient + ingredient.id)
|
||||
.then((r) => setCocktails(r.data))
|
||||
}
|
||||
|
||||
getCocktailsForCalcPage(load,setLoad, setCocktails, setCocktailMap, createError) {
|
||||
if (load) {
|
||||
return;
|
||||
}
|
||||
api().get(requests.cocktails.calc)
|
||||
.then((r) => {
|
||||
const data = r.data;
|
||||
if (data.length === 0) {
|
||||
setLoad(false);
|
||||
return;
|
||||
}
|
||||
setCocktails(data);
|
||||
let map = {};
|
||||
data.forEach((d) => {
|
||||
map = {
|
||||
...map,
|
||||
[d.id]: 1
|
||||
}
|
||||
})
|
||||
setCocktailMap(map);
|
||||
setLoad(true);
|
||||
})
|
||||
.catch((r) => {
|
||||
setLoad(true);
|
||||
createError("Ошибка загрузки данных от сервера Status:" + r.code)
|
||||
})
|
||||
}
|
||||
|
||||
savePhoto(event, changeCocktailValue, getError) {
|
||||
const file = event.target.files[0];
|
||||
let formData = new FormData();
|
||||
formData.append('file', file);
|
||||
api().post(requests.cocktails.photo, formData)
|
||||
.then((r) => changeCocktailValue("image", r.data))
|
||||
.catch(() => getError())
|
||||
}
|
||||
|
||||
deleteCocktailFromEdit(setCocktails, setCocktail, createError, cocktails, cocktail, emptyCocktail) {
|
||||
api().delete(requests.cocktails.cocktail + cocktail.id)
|
||||
.then(() => {
|
||||
setCocktails(cocktails.filter((r) => r.id !== cocktail.id))
|
||||
setCocktail(emptyCocktail);
|
||||
})
|
||||
.catch(() => createError("Ошибка удаления коктейля"))
|
||||
}
|
||||
|
||||
deleteCocktail(id, rows, setRows, createSuccess, createError) {
|
||||
api().delete(requests.cocktails.cocktail + id)
|
||||
.then(() => {
|
||||
setRows(rows.filter((r) => r.id !== id))
|
||||
createSuccess("Коктейль удален")
|
||||
})
|
||||
.catch(() => createError("Ошибка удаления коктейля"))
|
||||
}
|
||||
|
||||
async hiddenCocktail(id) {
|
||||
return api().post(requests.cocktails.hide + id);
|
||||
}
|
||||
|
||||
saveChangeCocktail (cocktail, createError, createSuccess) {
|
||||
api().patch(requests.cocktails.basic, cocktail)
|
||||
.then((r) => {
|
||||
if (!r.data.error) {
|
||||
createSuccess("Сохранено")
|
||||
return;
|
||||
}
|
||||
createError("Ошибка на сервере: " + r.data.error)
|
||||
})
|
||||
.catch(() => createError("Неизвестная ошибка"))
|
||||
}
|
||||
|
||||
getOneCocktail (selected, setCocktail, getError, emptyCocktail) {
|
||||
if (!selected) {
|
||||
setCocktail(emptyCocktail);
|
||||
return;
|
||||
}
|
||||
api().get(requests.cocktails.cocktail + selected)
|
||||
.then((r) => {
|
||||
setCocktail(r.data)
|
||||
})
|
||||
.catch(() => getError());
|
||||
}
|
||||
|
||||
getSimpleList(setCocktails, setSelected, setLoading, createError, currentId) {
|
||||
api().get(requests.cocktails.simple)
|
||||
.then((r) => {
|
||||
const arr = r.data.sort(getComparator("asc", "name"));
|
||||
setCocktails(arr)
|
||||
|
||||
if (!currentId) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
const currentCocktail = arr.find((r) => r.id === (currentId * 1));
|
||||
if (!currentCocktail) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
setSelected(currentCocktail.id);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(() => createError("Ошибка получения данных"))
|
||||
}
|
||||
|
||||
getCocktailForModal (row, setLoading, setCocktail, closeCocktail, getError) {
|
||||
setLoading(true)
|
||||
if (!row) {
|
||||
setLoading(false)
|
||||
return;
|
||||
}
|
||||
api().get(requests.cocktails.modal + row)
|
||||
.then((r) => {
|
||||
setCocktail(r.data)
|
||||
setLoading(false)
|
||||
})
|
||||
.catch(() => {
|
||||
getError();
|
||||
setLoading(false)
|
||||
closeCocktail();
|
||||
})
|
||||
}
|
||||
|
||||
changeFavourite(value, id, newState, setRows, createSuccess, createError) {
|
||||
const url = `${requests.cocktails.favourite}${id}`;
|
||||
const request = value ? api().put(url) : api().delete(url);
|
||||
|
||||
request
|
||||
.then(() => {
|
||||
setRows(newState);
|
||||
createSuccess("Спасибо за оценку!")
|
||||
}).catch(() => createError("Ошибка сохранения"))
|
||||
}
|
||||
|
||||
changeRating(id, newState, value, setRows, createSuccess, createError) {
|
||||
api().post(`${requests.cocktails.rating}${id}&rating=${value}`)
|
||||
.then(() => {
|
||||
setRows(newState);
|
||||
createSuccess("Спасибо за оценку!")
|
||||
}).catch(() => createError("Ошибка сохранения"))
|
||||
}
|
||||
|
||||
drinkCocktail(id, createSuccess, createError) {
|
||||
api().post(`${requests.cocktails.drink}/${id}`)
|
||||
.then(() => createSuccess("Бон аппетит"))
|
||||
.catch(() => createError("Ошибка отметки коктейля"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const cocktailClient = new CocktailClient();
|
||||
17
front/src/lib/clients/GlassClient.js
Normal file
17
front/src/lib/clients/GlassClient.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import {api} from "./api";
|
||||
import {requests} from "../../requests";
|
||||
import {getComparator} from "../../components/core/getComparator";
|
||||
|
||||
class GlassClient {
|
||||
|
||||
getGlassList(setGlass, createError) {
|
||||
api().get(requests.glass.list)
|
||||
.then((r) => setGlass(r.data.sort(getComparator())
|
||||
.map((item, i) => {
|
||||
return {id: i, name: item}
|
||||
})))
|
||||
.catch(() => createError("Ошибка получения посуды"))
|
||||
}
|
||||
}
|
||||
|
||||
export const glassClient = new GlassClient();
|
||||
112
front/src/lib/clients/IngredientClient.js
Normal file
112
front/src/lib/clients/IngredientClient.js
Normal file
@@ -0,0 +1,112 @@
|
||||
import {api} from "./api";
|
||||
import {requests} from "../../requests";
|
||||
import {getComparator} from "../../components/core/getComparator";
|
||||
|
||||
class IngredientClient {
|
||||
|
||||
allList(currentId, setIngredients, setIngredient, createError) {
|
||||
api().get(requests.ingredient.all)
|
||||
.then((r) => {
|
||||
const arr = r.data.sort(getComparator("asc", "name"));
|
||||
setIngredients(arr)
|
||||
|
||||
if (!currentId) {
|
||||
return;
|
||||
}
|
||||
const currentIngredient = arr.find((r) => r.id === (currentId * 1));
|
||||
if (!currentIngredient) {
|
||||
return;
|
||||
}
|
||||
setIngredient(currentIngredient);
|
||||
})
|
||||
.catch(() => createError("Ошибка получения данных"))
|
||||
}
|
||||
|
||||
getType(setTypes) {
|
||||
api().get(requests.ingredient.type)
|
||||
.then((r) => setTypes(r.data.sort(getComparator("asc", "name"))))
|
||||
}
|
||||
|
||||
findAll(setIngredients, createError) {
|
||||
api().get(requests.ingredient.all)
|
||||
.then((r) => setIngredients(r.data.sort(getComparator("asc", "name"))))
|
||||
.catch(() => createError("Ошибка получения списка ингредиентов"))
|
||||
}
|
||||
|
||||
getAllIngredients(setIngredients, setLoading, createError) {
|
||||
api().get(requests.ingredient.all)
|
||||
.then((r) => {
|
||||
setIngredients(r.data)
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
createError("Ошибка получения списка ингредиентов");
|
||||
setLoading(false);
|
||||
})
|
||||
}
|
||||
|
||||
changeIngredientIsHave(id, value, state, setIngredients, createError) {
|
||||
const url = `${requests.ingredient.crud}?id=${id}`;
|
||||
const request = value ? api().put(url) : api().delete(url);
|
||||
request
|
||||
.then(() => {
|
||||
setIngredients(state);
|
||||
})
|
||||
.catch(() => {
|
||||
createError("Ошибка изменения ингредиента");
|
||||
});
|
||||
}
|
||||
|
||||
deleteIngredientIsHave(id, createSuccess, createError) {
|
||||
api().delete(`${requests.ingredient.crud}/${id}`)
|
||||
.then(() => createSuccess("Ингредиент удален"))
|
||||
.catch(() => createError("Ошибка удаления ингредиента. Перезагрузите страницу"))
|
||||
}
|
||||
|
||||
saveIngredient(ingredient, createSuccess, createError) {
|
||||
api().patch(requests.ingredient.crud, ingredient)
|
||||
.then(() => createSuccess("Ингредиент сохранен"))
|
||||
.catch(() => createError("Ошибка сохранения"))
|
||||
}
|
||||
|
||||
findOne(id, selectIngredient, createError) {
|
||||
api().get(`${requests.bar.ingredient}?id=${id}`)
|
||||
.then((r) => {
|
||||
selectIngredient(r.data)
|
||||
})
|
||||
.catch(() => createError("Ошибка получения информации об ингредиенте"))
|
||||
}
|
||||
|
||||
changeIngredientInBar(ingredient, cocktail, setCocktail, createSuccess, createError) {
|
||||
const url = `${requests.ingredient.crud}?id=${ingredient.id}`;
|
||||
const request = ingredient.isHave ? api().delete(url) : api().put(url);
|
||||
const value = !ingredient.isHave;
|
||||
request.then(() => {
|
||||
const newReceipts = cocktail.receipt.map((r) => {
|
||||
if (r.ingredient.id !== ingredient.id) {
|
||||
return r;
|
||||
}
|
||||
return {
|
||||
...r,
|
||||
ingredient: {
|
||||
...ingredient,
|
||||
isHave: value
|
||||
}
|
||||
}
|
||||
})
|
||||
setCocktail({
|
||||
...cocktail,
|
||||
receipt: newReceipts
|
||||
})
|
||||
createSuccess("Сохранено")
|
||||
}).catch(() => createError("Ошибка сохранения"))
|
||||
}
|
||||
|
||||
findUnit(setUnits, createError) {
|
||||
api().get(requests.unit)
|
||||
.then((r) => setUnits(r.data.sort(getComparator("asc", "name"))))
|
||||
.catch(() => createError("Ошибка получения единиц измерения"))
|
||||
}
|
||||
}
|
||||
|
||||
export const ingredientClient = new IngredientClient()
|
||||
34
front/src/lib/clients/TokenUtil.js
Normal file
34
front/src/lib/clients/TokenUtil.js
Normal 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();
|
||||
17
front/src/lib/clients/UserClient.js
Normal file
17
front/src/lib/clients/UserClient.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import {requests} from "../../requests";
|
||||
import {api} from "./api";
|
||||
|
||||
class UserClient {
|
||||
|
||||
async getMe() {
|
||||
try{
|
||||
let url = requests.auth.getMe
|
||||
const response = await api().get(url);
|
||||
return {data: response.data}
|
||||
} catch (e) {
|
||||
return {errorData: e.data}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const userClient = new UserClient();
|
||||
16
front/src/lib/clients/api.js
Normal file
16
front/src/lib/clients/api.js
Normal 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;
|
||||
}
|
||||
11
front/src/lib/getSiteUrl.js
Normal file
11
front/src/lib/getSiteUrl.js
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user